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; }
static int CountCilInstructions(MemoryReader memReader) { int count = 0; while (memReader.NotEndOfBytes) { count++; OperationCode cilOpCode = memReader.ReadOpcode(); switch (cilOpCode) { case OperationCode.Ldarg_S: case OperationCode.Ldarga_S: case OperationCode.Starg_S: case OperationCode.Ldloc_S: case OperationCode.Ldloca_S: case OperationCode.Stloc_S: case OperationCode.Ldc_I4_S: 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: case OperationCode.Leave_S: case OperationCode.Unaligned_: case OperationCode.No_: memReader.SkipBytes(1); break; case OperationCode.Ldarg: case OperationCode.Ldarga: case OperationCode.Starg: case OperationCode.Ldloc: case OperationCode.Ldloca: case OperationCode.Stloc: memReader.SkipBytes(2); break; case OperationCode.Ldc_I4: case OperationCode.Jmp: case OperationCode.Call: case OperationCode.Calli: 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: case OperationCode.Callvirt: case OperationCode.Cpobj: case OperationCode.Ldobj: case OperationCode.Ldstr: case OperationCode.Newobj: case OperationCode.Castclass: case OperationCode.Isinst: case OperationCode.Unbox: case OperationCode.Ldfld: case OperationCode.Ldflda: case OperationCode.Stfld: case OperationCode.Ldsfld: case OperationCode.Ldsflda: case OperationCode.Stsfld: case OperationCode.Stobj: case OperationCode.Box: case OperationCode.Newarr: case OperationCode.Ldelema: case OperationCode.Ldelem: case OperationCode.Stelem: case OperationCode.Unbox_Any: case OperationCode.Refanyval: case OperationCode.Mkrefany: case OperationCode.Ldtoken: case OperationCode.Leave: case OperationCode.Ldftn: case OperationCode.Ldvirtftn: case OperationCode.Initobj: case OperationCode.Constrained_: case OperationCode.Sizeof: case OperationCode.Ldc_R4: memReader.SkipBytes(4); break; case OperationCode.Ldc_I8: case OperationCode.Ldc_R8: memReader.SkipBytes(8); break; case OperationCode.Switch: int numTargets = (int)memReader.ReadUInt32(); memReader.SkipBytes(4*numTargets); break; default: break; } } memReader.SeekOffset(0); return count; }
internal static SEHTableEntry[] GetFatSEHEntries( MemoryReader memReader, int numEntries ) { SEHTableEntry[] retSEHEntries = new SEHTableEntry[numEntries]; for (int i = 0; i < numEntries; ++i) { SEHFlags sehFlags = (SEHFlags)memReader.ReadUInt32(); uint tryOffset = memReader.ReadUInt32(); uint tryLength = memReader.ReadUInt32(); uint handlerOffset = memReader.ReadUInt32(); uint handlerLength = memReader.ReadUInt32(); uint classTokenOrFilterOffset = memReader.ReadUInt32(); retSEHEntries[i] = new SEHTableEntry(sehFlags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset); } return retSEHEntries; }
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 ReadStreamHeaders( ref MemoryReader memReader ) //^ requires this.ReaderState >= ReaderState.PEFile; { int numberOfStreams = this.StorageHeader.NumberOfStreams; this.StreamHeaders = new StreamHeader[numberOfStreams]; StreamHeader[] streamHeaders = this.StreamHeaders; for (int i = 0; i < numberOfStreams; ++i) { if (memReader.RemainingBytes < COR20Constants.MinimumSizeofStreamHeader) { this.ErrorContainer.AddDirectoryError(Directories.Cor20HeaderMetaData, memReader.Offset, MetadataReaderErrorKind.StreamHeaderTooSmall); return false; } streamHeaders[i].Offset = memReader.ReadUInt32(); streamHeaders[i].Size = memReader.ReadInt32(); // Review: Oh well there is no way i can test if we will read correctly. However we can check it after reading and aligning... streamHeaders[i].Name = memReader.ReadASCIINullTerminated(); memReader.Align(4); if (memReader.RemainingBytes < 0) { this.ErrorContainer.AddDirectoryError(Directories.Cor20HeaderMetaData, memReader.Offset, MetadataReaderErrorKind.NotEnoughSpaceForStreamHeaderName); return false; } } 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; }
bool ReadCOR20Header() //^ requires this.ReaderState >= ReaderState.PEFile; { MemoryBlock memBlock = this.DirectoryToMemoryBlock(this.OptionalHeaderDirectoryEntries.COR20HeaderTableDirectory); if (memBlock.Length < this.OptionalHeaderDirectoryEntries.COR20HeaderTableDirectory.Size) { this.ErrorContainer.AddDirectoryError(Directories.COR20Header, 0, MetadataReaderErrorKind.NotEnoughSpaceForCOR20HeaderTableDirectory); return false; } MemoryReader memReader = new MemoryReader(memBlock); if (memReader.RemainingBytes < COR20Constants.SizeOfCOR20Header) { this.ErrorContainer.AddDirectoryError(Directories.COR20Header, 0, MetadataReaderErrorKind.COR20HeaderTooSmall); return false; } this.COR20Header.CountBytes = memReader.ReadInt32(); this.COR20Header.MajorRuntimeVersion = memReader.ReadUInt16(); this.COR20Header.MinorRuntimeVersion = memReader.ReadUInt16(); this.COR20Header.MetaDataDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.COR20Header.MetaDataDirectory.Size = memReader.ReadUInt32(); this.COR20Header.COR20Flags = (COR20Flags)memReader.ReadUInt32(); this.COR20Header.EntryPointTokenOrRVA = memReader.ReadUInt32(); this.COR20Header.ResourcesDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.COR20Header.ResourcesDirectory.Size = memReader.ReadUInt32(); this.COR20Header.StrongNameSignatureDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.COR20Header.StrongNameSignatureDirectory.Size = memReader.ReadUInt32(); this.COR20Header.CodeManagerTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.COR20Header.CodeManagerTableDirectory.Size = memReader.ReadUInt32(); this.COR20Header.VtableFixupsDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.COR20Header.ExportAddressTableJumpsDirectory.Size = memReader.ReadUInt32(); this.COR20Header.ExportAddressTableJumpsDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.COR20Header.ExportAddressTableJumpsDirectory.Size = memReader.ReadUInt32(); this.COR20Header.ManagedNativeHeaderDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.COR20Header.ManagedNativeHeaderDirectory.Size = memReader.ReadUInt32(); return true; }
bool ReadMetadataHeader( ref MemoryReader memReader ) //^ requires this.ReaderState >= ReaderState.PEFile; { if (memReader.RemainingBytes < COR20Constants.MinimumSizeofMetadataHeader) { this.ErrorContainer.AddDirectoryError(Directories.Cor20HeaderMetaData, 0, MetadataReaderErrorKind.MetadataHeaderTooSmall); return false; } this.MetadataHeader.Signature = memReader.ReadUInt32(); if (this.MetadataHeader.Signature != COR20Constants.COR20MetadataSignature) { this.ErrorContainer.AddDirectoryError(Directories.Cor20HeaderMetaData, memReader.Offset - sizeof(uint), MetadataReaderErrorKind.MetadataSignature); return false; } this.MetadataHeader.MajorVersion = memReader.ReadUInt16(); this.MetadataHeader.MinorVersion = memReader.ReadUInt16(); this.MetadataHeader.ExtraData = memReader.ReadUInt32(); this.MetadataHeader.VersionStringSize = memReader.ReadInt32(); if (memReader.RemainingBytes < this.MetadataHeader.VersionStringSize) { this.ErrorContainer.AddDirectoryError(Directories.Cor20HeaderMetaData, memReader.Offset, MetadataReaderErrorKind.NotEnoughSpaceForVersionString); return false; } int numberOfBytesRead; this.MetadataHeader.VersionString = memReader.PeekUTF8NullTerminated(0, out numberOfBytesRead); memReader.SkipBytes(this.MetadataHeader.VersionStringSize); return true; }
bool ReadSectionHeaders( ref MemoryReader memReader ) //^ requires this.ReaderState >= ReaderState.Initialized; { int numberOfSections = this.COFFFileHeader.NumberOfSections; if (memReader.RemainingBytes < numberOfSections * PEFileConstants.SizeofSectionHeader) { this.ErrorContainer.AddBinaryError(memReader.Offset, MetadataReaderErrorKind.SectionHeadersTooSmall); return false; } this.SectionHeaders = new SectionHeader[numberOfSections]; SectionHeader[] sectionHeaderArray = this.SectionHeaders; for (int i = 0; i < numberOfSections; ++i) { sectionHeaderArray[i].Name = memReader.ReadASCIIWithSize(PEFileConstants.SizeofSectionName); sectionHeaderArray[i].VirtualSize = memReader.ReadInt32(); sectionHeaderArray[i].VirtualAddress = memReader.ReadInt32(); sectionHeaderArray[i].SizeOfRawData = memReader.ReadInt32(); sectionHeaderArray[i].OffsetToRawData = memReader.ReadInt32(); sectionHeaderArray[i].RVAToRelocations = memReader.ReadInt32(); sectionHeaderArray[i].PointerToLineNumbers = memReader.ReadInt32(); sectionHeaderArray[i].NumberOfRelocations = memReader.ReadUInt16(); sectionHeaderArray[i].NumberOfLineNumbers = memReader.ReadUInt16(); sectionHeaderArray[i].SectionCharacteristics = (SectionCharacteristics)memReader.ReadUInt32(); } return true; }
bool ReadPEFileLevelData() //^ requires this.ReaderState >= ReaderState.Initialized; { MemoryReader memReader = new MemoryReader(this.BinaryDocumentMemoryBlock.Pointer, this.BinaryDocumentMemoryBlock.Length); if (memReader.RemainingBytes < PEFileConstants.BasicPEHeaderSize) { this.ErrorContainer.AddBinaryError(0, MetadataReaderErrorKind.FileSizeTooSmall); return false; } // Look for DOS Signature "MZ" ushort dosSig = memReader.PeekUInt16(0); if (dosSig != PEFileConstants.DosSignature) { this.ErrorContainer.AddBinaryError(0, MetadataReaderErrorKind.DosHeader); return false; } // Skip the DOS Header int ntHeaderOffset = memReader.PeekInt32(PEFileConstants.PESignatureOffsetLocation); if (!memReader.SeekOffset(ntHeaderOffset)) { this.ErrorContainer.AddBinaryError(memReader.Offset, MetadataReaderErrorKind.FileSizeTooSmall); return false; } // Look for PESignature "PE\0\0" uint NTSignature = memReader.ReadUInt32(); if (NTSignature != PEFileConstants.PESignature) { this.ErrorContainer.AddBinaryError(memReader.Offset - sizeof(uint), MetadataReaderErrorKind.PESignature); return false; } // Read the COFF Header if (!this.ReadCOFFFileHeader(ref memReader)) { return false; } // Read the magic to determine if its PE or PE+ PEMagic magic = (PEMagic)memReader.PeekUInt16(0); switch (magic) { case PEMagic.PEMagic32: if ( !this.ReadOptionalHeaderStandardFields32(ref memReader) || !this.ReadOptionalHeaderNTAdditionalFields32(ref memReader) ) { return false; } break; case PEMagic.PEMagic64: if ( !this.ReadOptionalHeaderStandardFields64(ref memReader) || !this.ReadOptionalHeaderNTAdditionalFields64(ref memReader) ) { return false; } break; default: this.ErrorContainer.AddBinaryError(memReader.Offset, MetadataReaderErrorKind.UnknownPEMagic); return false; } if (!this.ReadOptionalHeaderDirectoryEntries(ref memReader)) { return false; } if (!this.ReadSectionHeaders(ref memReader)) { return false; } this.ReaderState = ReaderState.PEFile; this.Win32ResourceMemoryReader = new MemoryReader(this.DirectoryToMemoryBlock(this.OptionalHeaderDirectoryEntries.ResourceTableDirectory)); return true; }
bool ReadOptionalHeaderDirectoryEntries( ref MemoryReader memReader ) //^ requires this.ReaderState >= ReaderState.Initialized; { if (memReader.RemainingBytes < PEFileConstants.SizeofOptionalHeaderDirectoriesEntries) { this.ErrorContainer.AddBinaryError(memReader.Offset, MetadataReaderErrorKind.OptionalHeaderDirectoryEntriesTooSmall); return false; } this.OptionalHeaderDirectoryEntries.ExportTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.ExportTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.ImportTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.ImportTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.ResourceTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.ResourceTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.ExceptionTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.ExceptionTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.CertificateTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.CertificateTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.BaseRelocationTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.BaseRelocationTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.DebugTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.DebugTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.CopyrightTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.CopyrightTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.GlobalPointerTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.GlobalPointerTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.ThreadLocalStorageTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.ThreadLocalStorageTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.LoadConfigTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.LoadConfigTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.BoundImportTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.BoundImportTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.ImportAddressTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.ImportAddressTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.DelayImportTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.DelayImportTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.COR20HeaderTableDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.COR20HeaderTableDirectory.Size = memReader.ReadUInt32(); this.OptionalHeaderDirectoryEntries.ReservedDirectory.RelativeVirtualAddress = memReader.ReadInt32(); this.OptionalHeaderDirectoryEntries.ReservedDirectory.Size = memReader.ReadUInt32(); return true; }
bool ReadOptionalHeaderNTAdditionalFields64( ref MemoryReader memReader ) //^ requires this.ReaderState >= ReaderState.Initialized; { if (memReader.RemainingBytes < PEFileConstants.SizeofOptionalHeaderNTAdditionalFields64) { this.ErrorContainer.AddBinaryError(memReader.Offset, MetadataReaderErrorKind.OptionalHeaderNTAdditionalFields64TooSmall); return false; } this.OptionalHeaderNTAdditionalFields.ImageBase = memReader.ReadUInt64(); this.OptionalHeaderNTAdditionalFields.SectionAlignment = memReader.ReadInt32(); this.OptionalHeaderNTAdditionalFields.FileAlignment = memReader.ReadUInt32(); this.OptionalHeaderNTAdditionalFields.MajorOperatingSystemVersion = memReader.ReadUInt16(); this.OptionalHeaderNTAdditionalFields.MinorOperatingSystemVersion = memReader.ReadUInt16(); this.OptionalHeaderNTAdditionalFields.MajorImageVersion = memReader.ReadUInt16(); this.OptionalHeaderNTAdditionalFields.MinorImageVersion = memReader.ReadUInt16(); this.OptionalHeaderNTAdditionalFields.MajorSubsystemVersion = memReader.ReadUInt16(); this.OptionalHeaderNTAdditionalFields.MinorSubsystemVersion = memReader.ReadUInt16(); this.OptionalHeaderNTAdditionalFields.Win32VersionValue = memReader.ReadUInt32(); this.OptionalHeaderNTAdditionalFields.SizeOfImage = memReader.ReadInt32(); this.OptionalHeaderNTAdditionalFields.SizeOfHeaders = memReader.ReadInt32(); this.OptionalHeaderNTAdditionalFields.CheckSum = memReader.ReadUInt32(); this.OptionalHeaderNTAdditionalFields.Subsystem = (Subsystem)memReader.ReadUInt16(); this.OptionalHeaderNTAdditionalFields.DllCharacteristics = (DllCharacteristics)memReader.ReadUInt16(); this.OptionalHeaderNTAdditionalFields.SizeOfStackReserve = memReader.ReadUInt64(); this.OptionalHeaderNTAdditionalFields.SizeOfStackCommit = memReader.ReadUInt64(); this.OptionalHeaderNTAdditionalFields.SizeOfHeapReserve = memReader.ReadUInt64(); this.OptionalHeaderNTAdditionalFields.SizeOfHeapCommit = memReader.ReadUInt64(); this.OptionalHeaderNTAdditionalFields.LoaderFlags = memReader.ReadUInt32(); this.OptionalHeaderNTAdditionalFields.NumberOfRvaAndSizes = memReader.ReadInt32(); return true; }
private string ReadDebugInformationLocationFromDebugTableDirectoryData() { if (this.OptionalHeaderDirectoryEntries.DebugTableDirectory.Size != 0x1c) return string.Empty; var debugDirectoryReader = new MemoryReader(this.DirectoryToMemoryBlock(this.OptionalHeaderDirectoryEntries.DebugTableDirectory)); PeDebugDirectory debugDir = new PeDebugDirectory(); debugDir.Characteristics = debugDirectoryReader.ReadUInt32(); debugDir.TimeDateStamp = debugDirectoryReader.ReadUInt32(); debugDir.MajorVersion = debugDirectoryReader.ReadUInt16(); debugDir.MinorVersion = debugDirectoryReader.ReadUInt16(); debugDir.Type = debugDirectoryReader.ReadUInt32(); debugDir.SizeOfData = debugDirectoryReader.ReadUInt32(); debugDir.AddressOfRawData = debugDirectoryReader.ReadUInt32(); debugDir.PointerToRawData = debugDirectoryReader.ReadUInt32(); if (debugDir.SizeOfData == 0 ) return string.Empty; var dataBlock = new MemoryBlock(this.BinaryDocumentMemoryBlock.Pointer + debugDir.PointerToRawData, debugDir.SizeOfData); var ptrToDebugInfo = this.BinaryDocumentMemoryBlock.Pointer + debugDir.PointerToRawData; var ptrToDebugInfoEnd = this.BinaryDocumentMemoryBlock.Pointer + debugDir.PointerToRawData + debugDir.SizeOfData; if (ptrToDebugInfo >= this.BinaryDocumentMemoryBlock.Pointer + this.BinaryDocumentMemoryBlock.Length - 28) { //TODO: error return string.Empty; } if (ptrToDebugInfoEnd > this.BinaryDocumentMemoryBlock.Pointer + this.BinaryDocumentMemoryBlock.Length) { //TODO: error return string.Empty; } var debugDataReader = new MemoryReader(dataBlock); var magic = debugDataReader.ReadUInt32(); if (magic != 0x53445352) { //RSDS in little endian format //TODO: error return string.Empty; } var unknown1 = debugDataReader.ReadUInt32(); var unknown2 = debugDataReader.ReadUInt32(); var unknown3 = debugDataReader.ReadUInt32(); var unknown4 = debugDataReader.ReadUInt32(); var unknown5 = debugDataReader.ReadUInt32(); return debugDataReader.ReadASCIINullTerminated(); }
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; }
private PEFileDebugInformation ReadDebugInformationLocationFromDebugTableDirectoryData() { if (this.OptionalHeaderDirectoryEntries.DebugTableDirectory.Size != 0x1c) return new PEFileDebugInformation(); var debugDirectoryReader = new MemoryReader(this.DirectoryToMemoryBlock(this.OptionalHeaderDirectoryEntries.DebugTableDirectory)); PeDebugDirectory debugDir = new PeDebugDirectory(); debugDir.Characteristics = debugDirectoryReader.ReadUInt32(); debugDir.TimeDateStamp = debugDirectoryReader.ReadUInt32(); debugDir.MajorVersion = debugDirectoryReader.ReadUInt16(); debugDir.MinorVersion = debugDirectoryReader.ReadUInt16(); debugDir.Type = debugDirectoryReader.ReadUInt32(); debugDir.SizeOfData = debugDirectoryReader.ReadUInt32(); debugDir.AddressOfRawData = debugDirectoryReader.ReadUInt32(); debugDir.PointerToRawData = debugDirectoryReader.ReadUInt32(); if (debugDir.SizeOfData == 0) return new PEFileDebugInformation(); var dataBlock = new MemoryBlock(this.BinaryDocumentMemoryBlock.Pointer + debugDir.PointerToRawData, debugDir.SizeOfData); var ptrToDebugInfo = this.BinaryDocumentMemoryBlock.Pointer + debugDir.PointerToRawData; var ptrToDebugInfoEnd = this.BinaryDocumentMemoryBlock.Pointer + debugDir.PointerToRawData + debugDir.SizeOfData; if (ptrToDebugInfo >= this.BinaryDocumentMemoryBlock.Pointer + this.BinaryDocumentMemoryBlock.Length - 28) { //TODO: error return new PEFileDebugInformation(); } if (ptrToDebugInfoEnd > this.BinaryDocumentMemoryBlock.Pointer + this.BinaryDocumentMemoryBlock.Length) { //TODO: error return new PEFileDebugInformation(); } var debugDataReader = new MemoryReader(dataBlock); var magic = debugDataReader.ReadUInt32(); if (magic != 0x53445352) { //RSDS in little endian format //TODO: error return new PEFileDebugInformation(); } var guid = debugDataReader.PeekGuid(0); debugDataReader.SkipBytes(16); UInt32 age = debugDataReader.ReadUInt32(); string fileName = debugDataReader.ReadASCIINullTerminated(); var guidHex = guid.ToString("N"); string ageHex = age.ToString("X"); string version = guidHex + ageHex; PEFileDebugInformation information = new PEFileDebugInformation(); information.Signature = guid; information.Age = age; information.PdbVersion = version; information.PdbFileName = fileName; return information; }