internal MethodIL/*?*/ GetMethodIL( uint methodDefRowId ) { MethodRow methodRow = this.MethodTable[methodDefRowId]; if ( (methodRow.ImplFlags & MethodImplFlags.CodeTypeMask) != MethodImplFlags.ILCodeType || methodRow.RVA == 0 ) { return null; } MemoryBlock memBlock = this.RVAToMemoryBlock(methodRow.RVA); // Error need to check if the Memory Block is empty. This is calse for all the calls... MemoryReader memReader = new MemoryReader(memBlock); byte headByte = memReader.ReadByte(); if ((headByte & CILMethodFlags.ILFormatMask) == CILMethodFlags.ILTinyFormat) { int size = headByte >> CILMethodFlags.ILTinyFormatSizeShift; return new MethodIL( true, 8, 0x00000000, memReader.GetMemoryBlockAt(0, size), null ); } else if ((headByte & CILMethodFlags.ILFormatMask) != CILMethodFlags.ILFatFormat) { // PEFileFormat Error... return null; } // FatILFormat byte headByte2 = memReader.ReadByte(); if ((headByte2 >> CILMethodFlags.ILFatFormatHeaderSizeShift) != CILMethodFlags.ILFatFormatHeaderSize) { // PEFile Format Error... return null; } bool localVarInited = (headByte & CILMethodFlags.ILInitLocals) == CILMethodFlags.ILInitLocals; bool moreSectsPresent = (headByte & CILMethodFlags.ILMoreSects) == CILMethodFlags.ILMoreSects; ushort maxStack = memReader.ReadUInt16(); int codeSize = memReader.ReadInt32(); uint localSignatureToken = memReader.ReadUInt32(); MemoryBlock ilCodeMemBlock = memReader.GetMemoryBlockAt(0, codeSize); SEHTableEntry[]/*?*/ sehTableEntries = null; if (moreSectsPresent) { memReader.SkipBytes(codeSize); memReader.Align(4); byte sectHeader = memReader.ReadByte(); if ((sectHeader & CILMethodFlags.SectEHTable) != CILMethodFlags.SectEHTable) { // PEFile Format Error... return null; } bool sectFatFormat = (sectHeader & CILMethodFlags.SectFatFormat) == CILMethodFlags.SectFatFormat; int dataSize = memReader.ReadByte(); if (sectFatFormat) { dataSize += (int)memReader.ReadUInt16() << 8; sehTableEntries = PEFileReader.GetFatSEHEntries(memReader, dataSize / 24); } else { memReader.SkipBytes(2); //skip over reserved field sehTableEntries = PEFileReader.GetSmallSEHEntries(memReader, dataSize / 12); } } return new MethodIL( localVarInited, maxStack, localSignatureToken, ilCodeMemBlock, sehTableEntries ); }
bool PopulateCilInstructions() { MethodBodyDocument document = new MethodBodyDocument(this.MethodDefinition); MemoryReader memReader = new MemoryReader(this.MethodIL.EncodedILMemoryBlock); var numInstructions = CountCilInstructions(memReader); if (numInstructions == 0) return true; CilInstruction[] instrList = new CilInstruction[numInstructions]; int instructionNumber = 0; while (memReader.NotEndOfBytes) { object/*?*/ value = null; uint offset = (uint)memReader.Offset; OperationCode cilOpCode = memReader.ReadOpcode(); switch (cilOpCode) { case OperationCode.Nop: case OperationCode.Break: break; case OperationCode.Ldarg_0: case OperationCode.Ldarg_1: case OperationCode.Ldarg_2: case OperationCode.Ldarg_3: value = this.GetParameter((uint)(cilOpCode - OperationCode.Ldarg_0)); break; case OperationCode.Ldloc_0: case OperationCode.Ldloc_1: case OperationCode.Ldloc_2: case OperationCode.Ldloc_3: value = this.GetLocal((uint)(cilOpCode - OperationCode.Ldloc_0)); break; case OperationCode.Stloc_0: case OperationCode.Stloc_1: case OperationCode.Stloc_2: case OperationCode.Stloc_3: value = this.GetLocal((uint)(cilOpCode - OperationCode.Stloc_0)); break; case OperationCode.Ldarg_S: case OperationCode.Ldarga_S: case OperationCode.Starg_S: value = this.GetParameter(memReader.ReadByte()); break; case OperationCode.Ldloc_S: case OperationCode.Ldloca_S: case OperationCode.Stloc_S: value = this.GetLocal(memReader.ReadByte()); break; case OperationCode.Ldnull: case OperationCode.Ldc_I4_M1: case OperationCode.Ldc_I4_0: case OperationCode.Ldc_I4_1: case OperationCode.Ldc_I4_2: case OperationCode.Ldc_I4_3: case OperationCode.Ldc_I4_4: case OperationCode.Ldc_I4_5: case OperationCode.Ldc_I4_6: case OperationCode.Ldc_I4_7: case OperationCode.Ldc_I4_8: break; case OperationCode.Ldc_I4_S: value = (int)memReader.ReadSByte(); break; case OperationCode.Ldc_I4: value = memReader.ReadInt32(); break; case OperationCode.Ldc_I8: value = memReader.ReadInt64(); break; case OperationCode.Ldc_R4: value = memReader.ReadSingle(); break; case OperationCode.Ldc_R8: value = memReader.ReadDouble(); break; case OperationCode.Dup: case OperationCode.Pop: break; case OperationCode.Jmp: value = this.GetMethod(memReader.ReadUInt32()); break; case OperationCode.Call: { IMethodReference methodReference = this.GetMethod(memReader.ReadUInt32()); IArrayTypeReference/*?*/ arrayType = methodReference.ContainingType as IArrayTypeReference; if (arrayType != null) { // For Get(), Set() and Address() on arrays, the runtime provides method implementations. // Hence, CCI2 replaces these with pseudo instrcutions Array_Set, Array_Get and Array_Addr. // All other methods on arrays will not use pseudo instruction and will have methodReference as their operand. if (methodReference.Name.UniqueKey == this.PEFileToObjectModel.NameTable.Set.UniqueKey) { cilOpCode = OperationCode.Array_Set; value = arrayType; } else if (methodReference.Name.UniqueKey == this.PEFileToObjectModel.NameTable.Get.UniqueKey) { cilOpCode = OperationCode.Array_Get; value = arrayType; } else if (methodReference.Name.UniqueKey == this.PEFileToObjectModel.NameTable.Address.UniqueKey) { cilOpCode = OperationCode.Array_Addr; value = arrayType; } else { value = methodReference; } } else { value = methodReference; } } break; case OperationCode.Calli: value = this.GetFunctionPointerType(memReader.ReadUInt32()); break; case OperationCode.Ret: break; case OperationCode.Br_S: case OperationCode.Brfalse_S: case OperationCode.Brtrue_S: case OperationCode.Beq_S: case OperationCode.Bge_S: case OperationCode.Bgt_S: case OperationCode.Ble_S: case OperationCode.Blt_S: case OperationCode.Bne_Un_S: case OperationCode.Bge_Un_S: case OperationCode.Bgt_Un_S: case OperationCode.Ble_Un_S: case OperationCode.Blt_Un_S: { uint jumpOffset = (uint)(memReader.Offset + 1 + memReader.ReadSByte()); if (jumpOffset >= this.EndOfMethodOffset) { // Error... } value = jumpOffset; } break; case OperationCode.Br: case OperationCode.Brfalse: case OperationCode.Brtrue: case OperationCode.Beq: case OperationCode.Bge: case OperationCode.Bgt: case OperationCode.Ble: case OperationCode.Blt: case OperationCode.Bne_Un: case OperationCode.Bge_Un: case OperationCode.Bgt_Un: case OperationCode.Ble_Un: case OperationCode.Blt_Un: { uint jumpOffset = (uint)(memReader.Offset + 4 + memReader.ReadInt32()); if (jumpOffset >= this.EndOfMethodOffset) { // Error... } value = jumpOffset; } break; case OperationCode.Switch: { uint numTargets = memReader.ReadUInt32(); uint[] result = new uint[numTargets]; uint asOffset = memReader.Offset + numTargets * 4; for (int i = 0; i < numTargets; i++) { uint targetAddress = memReader.ReadUInt32() + asOffset; if (targetAddress >= this.EndOfMethodOffset) { // Error... } result[i] = targetAddress; } value = result; } break; case OperationCode.Ldind_I1: case OperationCode.Ldind_U1: case OperationCode.Ldind_I2: case OperationCode.Ldind_U2: case OperationCode.Ldind_I4: case OperationCode.Ldind_U4: case OperationCode.Ldind_I8: case OperationCode.Ldind_I: case OperationCode.Ldind_R4: case OperationCode.Ldind_R8: case OperationCode.Ldind_Ref: case OperationCode.Stind_Ref: case OperationCode.Stind_I1: case OperationCode.Stind_I2: case OperationCode.Stind_I4: case OperationCode.Stind_I8: case OperationCode.Stind_R4: case OperationCode.Stind_R8: case OperationCode.Add: case OperationCode.Sub: case OperationCode.Mul: case OperationCode.Div: case OperationCode.Div_Un: case OperationCode.Rem: case OperationCode.Rem_Un: case OperationCode.And: case OperationCode.Or: case OperationCode.Xor: case OperationCode.Shl: case OperationCode.Shr: case OperationCode.Shr_Un: case OperationCode.Neg: case OperationCode.Not: case OperationCode.Conv_I1: case OperationCode.Conv_I2: case OperationCode.Conv_I4: case OperationCode.Conv_I8: case OperationCode.Conv_R4: case OperationCode.Conv_R8: case OperationCode.Conv_U4: case OperationCode.Conv_U8: break; case OperationCode.Callvirt: { IMethodReference methodReference = this.GetMethod(memReader.ReadUInt32()); IArrayTypeReference/*?*/ arrayType = methodReference.ContainingType as IArrayTypeReference; if (arrayType != null) { // For Get(), Set() and Address() on arrays, the runtime provides method implementations. // Hence, CCI2 replaces these with pseudo instructions Array_Set, Array_Get and Array_Addr. // All other methods on arrays will not use pseudo instruction and will have methodReference as their operand. if (methodReference.Name.UniqueKey == this.PEFileToObjectModel.NameTable.Set.UniqueKey) { cilOpCode = OperationCode.Array_Set; value = arrayType; } else if (methodReference.Name.UniqueKey == this.PEFileToObjectModel.NameTable.Get.UniqueKey) { cilOpCode = OperationCode.Array_Get; value = arrayType; } else if (methodReference.Name.UniqueKey == this.PEFileToObjectModel.NameTable.Address.UniqueKey) { cilOpCode = OperationCode.Array_Addr; value = arrayType; } else { value = methodReference; } } else { value = methodReference; } } break; case OperationCode.Cpobj: case OperationCode.Ldobj: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Ldstr: value = this.GetUserStringForToken(memReader.ReadUInt32()); break; case OperationCode.Newobj: { IMethodReference methodReference = this.GetMethod(memReader.ReadUInt32()); IArrayTypeReference/*?*/ arrayType = methodReference.ContainingType as IArrayTypeReference; if (arrayType != null && !arrayType.IsVector) { uint numParam = IteratorHelper.EnumerableCount(methodReference.Parameters); if (numParam != arrayType.Rank) cilOpCode = OperationCode.Array_Create_WithLowerBound; else cilOpCode = OperationCode.Array_Create; value = arrayType; } else { value = methodReference; } } break; case OperationCode.Castclass: case OperationCode.Isinst: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Conv_R_Un: break; case OperationCode.Unbox: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Throw: break; case OperationCode.Ldfld: case OperationCode.Ldflda: case OperationCode.Stfld: value = this.GetField(memReader.ReadUInt32()); break; case OperationCode.Ldsfld: case OperationCode.Ldsflda: case OperationCode.Stsfld: value = this.GetField(memReader.ReadUInt32()); var fieldRef = value as FieldReference; if (fieldRef != null) fieldRef.isStatic = true; break; case OperationCode.Stobj: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Conv_Ovf_I1_Un: case OperationCode.Conv_Ovf_I2_Un: case OperationCode.Conv_Ovf_I4_Un: case OperationCode.Conv_Ovf_I8_Un: case OperationCode.Conv_Ovf_U1_Un: case OperationCode.Conv_Ovf_U2_Un: case OperationCode.Conv_Ovf_U4_Un: case OperationCode.Conv_Ovf_U8_Un: case OperationCode.Conv_Ovf_I_Un: case OperationCode.Conv_Ovf_U_Un: break; case OperationCode.Box: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Newarr: { var elementType = this.GetType(memReader.ReadUInt32()); if (elementType != null) value = Vector.GetVector(elementType, PEFileToObjectModel.InternFactory); else value = Dummy.ArrayType; } break; case OperationCode.Ldlen: break; case OperationCode.Ldelema: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Ldelem_I1: case OperationCode.Ldelem_U1: case OperationCode.Ldelem_I2: case OperationCode.Ldelem_U2: case OperationCode.Ldelem_I4: case OperationCode.Ldelem_U4: case OperationCode.Ldelem_I8: case OperationCode.Ldelem_I: case OperationCode.Ldelem_R4: case OperationCode.Ldelem_R8: case OperationCode.Ldelem_Ref: case OperationCode.Stelem_I: case OperationCode.Stelem_I1: case OperationCode.Stelem_I2: case OperationCode.Stelem_I4: case OperationCode.Stelem_I8: case OperationCode.Stelem_R4: case OperationCode.Stelem_R8: case OperationCode.Stelem_Ref: break; case OperationCode.Ldelem: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Stelem: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Unbox_Any: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Conv_Ovf_I1: case OperationCode.Conv_Ovf_U1: case OperationCode.Conv_Ovf_I2: case OperationCode.Conv_Ovf_U2: case OperationCode.Conv_Ovf_I4: case OperationCode.Conv_Ovf_U4: case OperationCode.Conv_Ovf_I8: case OperationCode.Conv_Ovf_U8: break; case OperationCode.Refanyval: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Ckfinite: break; case OperationCode.Mkrefany: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Ldtoken: value = this.GetRuntimeHandleFromToken(memReader.ReadUInt32()); break; case OperationCode.Conv_U2: case OperationCode.Conv_U1: case OperationCode.Conv_I: case OperationCode.Conv_Ovf_I: case OperationCode.Conv_Ovf_U: case OperationCode.Add_Ovf: case OperationCode.Add_Ovf_Un: case OperationCode.Mul_Ovf: case OperationCode.Mul_Ovf_Un: case OperationCode.Sub_Ovf: case OperationCode.Sub_Ovf_Un: case OperationCode.Endfinally: break; case OperationCode.Leave: { uint leaveOffset = (uint)(memReader.Offset + 4 + memReader.ReadInt32()); if (leaveOffset >= this.EndOfMethodOffset) { // Error... } value = leaveOffset; } break; case OperationCode.Leave_S: { uint leaveOffset = (uint)(memReader.Offset + 1 + memReader.ReadSByte()); if (leaveOffset >= this.EndOfMethodOffset) { // Error... } value = leaveOffset; } break; case OperationCode.Stind_I: case OperationCode.Conv_U: case OperationCode.Arglist: case OperationCode.Ceq: case OperationCode.Cgt: case OperationCode.Cgt_Un: case OperationCode.Clt: case OperationCode.Clt_Un: break; case OperationCode.Ldftn: case OperationCode.Ldvirtftn: value = this.GetMethod(memReader.ReadUInt32()); break; case OperationCode.Ldarg: case OperationCode.Ldarga: case OperationCode.Starg: value = this.GetParameter(memReader.ReadUInt16()); break; case OperationCode.Ldloc: case OperationCode.Ldloca: case OperationCode.Stloc: value = this.GetLocal(memReader.ReadUInt16()); break; case OperationCode.Localloc: value = PointerType.GetPointerType(this.PEFileToObjectModel.PlatformType.SystemVoid, this.PEFileToObjectModel.InternFactory); break; case OperationCode.Endfilter: break; case OperationCode.Unaligned_: value = memReader.ReadByte(); break; case OperationCode.Volatile_: case OperationCode.Tail_: break; case OperationCode.Initobj: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Constrained_: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Cpblk: case OperationCode.Initblk: break; case OperationCode.No_: value = (OperationCheckFlags)memReader.ReadByte(); break; case OperationCode.Rethrow: break; case OperationCode.Sizeof: value = this.GetType(memReader.ReadUInt32()); break; case OperationCode.Refanytype: case OperationCode.Readonly_: break; default: this.PEFileToObjectModel.PEFileReader.ErrorContainer.AddILError(this.MethodDefinition, offset, MetadataReaderErrorKind.UnknownILInstruction); break; } instrList[instructionNumber++] = new CilInstruction(cilOpCode, document, offset, value); } this.MethodBody.SetCilInstructions(instrList); return true; }
bool ReadMetadataTableInformation( ref MemoryReader memReader ) //^ requires this.ReaderState >= ReaderState.CORModule; { if (memReader.RemainingBytes < MetadataStreamConstants.SizeOfMetadataTableHeader) { this.ErrorContainer.AddMetadataStreamError(this.MetadataStreamName, 0, MetadataReaderErrorKind.MetadataTableHeaderTooSmall); return false; } this.MetadataTableHeader.Reserved = memReader.ReadUInt32(); this.MetadataTableHeader.MajorVersion = memReader.ReadByte(); this.MetadataTableHeader.MinorVersion = memReader.ReadByte(); this.MetadataTableHeader.HeapSizeFlags = (HeapSizeFlag)memReader.ReadByte(); this.MetadataTableHeader.RowId = memReader.ReadByte(); this.MetadataTableHeader.ValidTables = (TableMask)memReader.ReadUInt64(); this.MetadataTableHeader.SortedTables = (TableMask)memReader.ReadUInt64(); ulong presentTables = (ulong)this.MetadataTableHeader.ValidTables; ulong validTablesForVersion = 0; int version = this.MetadataTableHeader.MajorVersion << 16 | this.MetadataTableHeader.MinorVersion; switch (version) { case 0x00010000: validTablesForVersion = (ulong)TableMask.V1_0_TablesMask; break; case 0x00010001: validTablesForVersion = (ulong)TableMask.V1_1_TablesMask; break; case 0x00020000: validTablesForVersion = (ulong)TableMask.V2_0_TablesMask; break; default: this.ErrorContainer.AddMetadataStreamError(this.MetadataStreamName, 4, MetadataReaderErrorKind.UnknownVersionOfMetadata); return false; } if ((presentTables & ~validTablesForVersion) != 0) { this.ErrorContainer.AddMetadataStreamError(this.MetadataStreamName, 8, MetadataReaderErrorKind.UnknownTables); return false; } if (this.MetadataStreamKind == MetadataStreamKind.Compressed && (presentTables & (ulong)TableMask.CompressedStreamNotAllowedMask) != 0) { this.ErrorContainer.AddMetadataStreamError(this.MetadataStreamName, 8, MetadataReaderErrorKind.IllegalTablesInCompressedMetadataStream); return false; } ulong requiredSortedTables = presentTables & validTablesForVersion & (ulong)TableMask.SortedTablesMask; if ((requiredSortedTables & (ulong)this.MetadataTableHeader.SortedTables) != requiredSortedTables) { this.ErrorContainer.AddMetadataStreamError(this.MetadataStreamName, 16, MetadataReaderErrorKind.SomeRequiredTablesNotSorted); //Carry on regardless. There are/were compiler out there that sort the required tables, but fail to set the bit in SortedTables. } int numberOfTables = this.MetadataTableHeader.GetNumberOfTablesPresent(); if (memReader.RemainingBytes < numberOfTables * sizeof(Int32)) { this.ErrorContainer.AddMetadataStreamError(this.MetadataStreamName, memReader.Offset, MetadataReaderErrorKind.TableRowCountSpaceTooSmall); return false; } this.MetadataTableRowCount = new uint[numberOfTables]; uint[] metadataTableRowCount = this.MetadataTableRowCount; for (int i = 0; i < numberOfTables; ++i) { metadataTableRowCount[i] = memReader.ReadUInt32(); } return true; }
internal static SEHTableEntry[] GetSmallSEHEntries( MemoryReader memReader, int numEntries ) { SEHTableEntry[] retSEHEntries = new SEHTableEntry[numEntries]; for (int i = 0; i < numEntries; ++i) { SEHFlags sehFlags = (SEHFlags)memReader.ReadUInt16(); uint tryOffset = memReader.ReadUInt16(); uint tryLength = memReader.ReadByte(); uint handlerOffset = memReader.ReadUInt16(); uint handlerLength = memReader.ReadByte(); uint classTokenOrFilterOffset = memReader.ReadUInt32(); retSEHEntries[i] = new SEHTableEntry(sehFlags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset); } return retSEHEntries; }
bool ReadOptionalHeaderStandardFields64( ref MemoryReader memReader ) //^ requires this.ReaderState >= ReaderState.Initialized; { if (memReader.RemainingBytes < PEFileConstants.SizeofOptionalHeaderStandardFields64) { this.ErrorContainer.AddBinaryError(memReader.Offset, MetadataReaderErrorKind.OptionalHeaderStandardFields64TooSmall); return false; } this.OptionalHeaderStandardFields.PEMagic = (PEMagic)memReader.ReadUInt16(); this.OptionalHeaderStandardFields.MajorLinkerVersion = memReader.ReadByte(); this.OptionalHeaderStandardFields.MinorLinkerVersion = memReader.ReadByte(); this.OptionalHeaderStandardFields.SizeOfCode = memReader.ReadInt32(); this.OptionalHeaderStandardFields.SizeOfInitializedData = memReader.ReadInt32(); this.OptionalHeaderStandardFields.SizeOfUninitializedData = memReader.ReadInt32(); this.OptionalHeaderStandardFields.RVAOfEntryPoint = memReader.ReadInt32(); this.OptionalHeaderStandardFields.BaseOfCode = memReader.ReadInt32(); return true; }
internal int GetMethodRefGenericParameterCount( MethodReference moduleMethodReference ) { uint signatureBlobOffset = this.PEFileReader.MemberRefTable.GetSignature(moduleMethodReference.MemberRefRowId); // TODO: error checking offset in range MemoryBlock signatureMemoryBlock = this.PEFileReader.BlobStream.GetMemoryBlockAt(signatureBlobOffset); // TODO: Error checking enough space in signature memoryBlock. MemoryReader memoryReader = new MemoryReader(signatureMemoryBlock); // TODO: Check if this is really method signature there. byte firstByte = memoryReader.ReadByte(); if (SignatureHeader.IsGeneric(firstByte)) { return memoryReader.ReadCompressedUInt32(); } return 0; }
internal IMarshallingInformation GetMarshallingInformation( MetadataObject metadataObject ) { uint fieldMarshalRowId = this.PEFileReader.FieldMarshalTable.GetFieldMarshalRowId(metadataObject.TokenValue); if (fieldMarshalRowId == 0) return Dummy.MarshallingInformation; FieldMarshalRow fieldMarshalRow = this.PEFileReader.FieldMarshalTable[fieldMarshalRowId]; MemoryBlock fieldMarshalMemoryBlock = this.PEFileReader.BlobStream.GetMemoryBlockAt(fieldMarshalRow.NativeType); MemoryReader memoryReader = new MemoryReader(fieldMarshalMemoryBlock); System.Runtime.InteropServices.UnmanagedType unmanagedType = (System.Runtime.InteropServices.UnmanagedType)memoryReader.ReadByte(); if (memoryReader.NotEndOfBytes) { if (unmanagedType == System.Runtime.InteropServices.UnmanagedType.ByValArray) { uint numElements = (uint)memoryReader.ReadCompressedUInt32(); System.Runtime.InteropServices.UnmanagedType elementType = System.Runtime.InteropServices.UnmanagedType.AsAny; if (memoryReader.NotEndOfBytes) elementType = (System.Runtime.InteropServices.UnmanagedType)memoryReader.ReadByte(); return new ByValArrayMarshallingInformation(elementType, numElements); } else if (unmanagedType == System.Runtime.InteropServices.UnmanagedType.CustomMarshaler) { string marshallerName; string marshallerArgument; memoryReader.ReadInt16(); // Deliberate Skip... int byteLen = memoryReader.ReadCompressedUInt32(); if (byteLen == -1 || byteLen == 0) marshallerName = string.Empty; else marshallerName = memoryReader.ReadUTF8WithSize(byteLen); ITypeReference/*?*/ marshaller = this.GetSerializedTypeNameAsTypeReference(marshallerName); if (marshaller == null) marshaller = Dummy.TypeReference; byteLen = memoryReader.ReadCompressedUInt32(); if (byteLen == -1 || byteLen == 0) marshallerArgument = string.Empty; else marshallerArgument = memoryReader.ReadUTF8WithSize(byteLen); return new CustomMarshallingInformation(marshaller, marshallerArgument); } else if (unmanagedType == System.Runtime.InteropServices.UnmanagedType.LPArray) { System.Runtime.InteropServices.UnmanagedType elementType = (System.Runtime.InteropServices.UnmanagedType)memoryReader.ReadByte(); int paramIndex = -1; uint flag = 0; uint numElements = 0; if (memoryReader.NotEndOfBytes) paramIndex = (int)memoryReader.ReadCompressedUInt32(); if (memoryReader.NotEndOfBytes) numElements = (uint)memoryReader.ReadCompressedUInt32(); if (memoryReader.NotEndOfBytes) { flag = (uint)memoryReader.ReadCompressedUInt32(); if (flag == 0) { //TODO: check that paramIndex is 0 paramIndex = -1; //paramIndex is just a place holder so that numElements can be present } } return new LPArrayMarshallingInformation(elementType, paramIndex, numElements); } else if (unmanagedType == System.Runtime.InteropServices.UnmanagedType.SafeArray) { System.Runtime.InteropServices.VarEnum elementType = (System.Runtime.InteropServices.VarEnum)memoryReader.ReadByte(); string subType = string.Empty; if (memoryReader.NotEndOfBytes) { int byteLen = memoryReader.ReadCompressedUInt32(); if (byteLen > 0) subType = memoryReader.ReadUTF8WithSize(byteLen); } ITypeReference/*?*/ subTypeRef = this.GetSerializedTypeNameAsTypeReference(subType); if (subTypeRef == null) subTypeRef = Dummy.TypeReference; return new SafeArrayMarshallingInformation(elementType, subTypeRef); } else if (unmanagedType == System.Runtime.InteropServices.UnmanagedType.ByValTStr) { uint numElements = (uint)memoryReader.ReadCompressedUInt32(); return new ByValTStrMarshallingInformation(numElements); } else if (unmanagedType == System.Runtime.InteropServices.UnmanagedType.Interface) { uint iidParameterIndex = (uint)memoryReader.ReadCompressedUInt32(); return new IidParameterIndexMarshallingInformation(iidParameterIndex); } else { //TODO: error blob should not have extra info unless one of the above types. } } return new SimpleMarshallingInformation(unmanagedType); }
internal IMetadataConstant GetDefaultValue( MetadataObject metadataObject ) { uint constRowId = this.PEFileReader.ConstantTable.GetConstantRowId(metadataObject.TokenValue); if (constRowId == 0) return Dummy.Constant; ConstantRow constRow = this.PEFileReader.ConstantTable[constRowId]; MemoryBlock constValueMemoryBlock = this.PEFileReader.BlobStream.GetMemoryBlockAt(constRow.Value); MemoryReader memoryReader = new MemoryReader(constValueMemoryBlock); switch (constRow.Type) { case ElementType.Boolean: { byte val = memoryReader.ReadByte(); return new ConstantExpression(this.PlatformType.SystemBoolean, val != 0); } case ElementType.Char: return new ConstantExpression(this.PlatformType.SystemChar, memoryReader.ReadChar()); case ElementType.Int8: return new ConstantExpression(this.PlatformType.SystemInt8, memoryReader.ReadSByte()); case ElementType.Int16: return new ConstantExpression(this.PlatformType.SystemInt16, memoryReader.ReadInt16()); case ElementType.Int32: return new ConstantExpression(this.PlatformType.SystemInt32, memoryReader.ReadInt32()); case ElementType.Int64: return new ConstantExpression(this.PlatformType.SystemInt64, memoryReader.ReadInt64()); case ElementType.UInt8: return new ConstantExpression(this.PlatformType.SystemUInt8, memoryReader.ReadByte()); case ElementType.UInt16: return new ConstantExpression(this.PlatformType.SystemUInt16, memoryReader.ReadUInt16()); case ElementType.UInt32: return new ConstantExpression(this.PlatformType.SystemUInt32, memoryReader.ReadUInt32()); case ElementType.UInt64: return new ConstantExpression(this.PlatformType.SystemUInt64, memoryReader.ReadUInt64()); case ElementType.Single: return new ConstantExpression(this.PlatformType.SystemFloat32, memoryReader.ReadSingle()); case ElementType.Double: return new ConstantExpression(this.PlatformType.SystemFloat64, memoryReader.ReadDouble()); case ElementType.String: { int byteLen = memoryReader.Length; string/*?*/ value; if (byteLen == -1) { value = null; } else if (byteLen == 0) { value = string.Empty; } else { value = memoryReader.ReadUTF16WithSize(byteLen); } return new ConstantExpression(this.PlatformType.SystemString, value); } case ElementType.Class: return new ConstantExpression(this.PlatformType.SystemObject, null); } // MDError... return Dummy.Constant; }
internal ushort GetMethodParameterCount( MethodDefinition moduleMethod ) { uint signatureBlobOffset = this.PEFileReader.MethodTable.GetSignature(moduleMethod.MethodDefRowId); // TODO: error checking offset in range MemoryBlock signatureMemoryBlock = this.PEFileReader.BlobStream.GetMemoryBlockAt(signatureBlobOffset); // TODO: Error checking enough space in signature memoryBlock. MemoryReader memoryReader = new MemoryReader(signatureMemoryBlock); byte firstByte = memoryReader.ReadByte(); if (SignatureHeader.IsGeneric(firstByte)) { memoryReader.ReadCompressedUInt32(); } return (ushort)memoryReader.ReadCompressedUInt32(); }