public void Serialize(BlobBuilder builder, PEDirectoriesBuilder headers, out ContentId contentId) { var serializedSections = SerializeSections(); Blob stampFixup; WritePESignature(builder); WriteCoffHeader(builder, serializedSections, out stampFixup); WritePEHeader(builder, headers, serializedSections); WriteSectionHeaders(builder, serializedSections); builder.Align(FileAlignment); foreach (var section in serializedSections) { builder.LinkSuffix(section.Builder); builder.Align(FileAlignment); } contentId = IdProvider(builder); // patch timestamp in COFF header: var stampWriter = new BlobWriter(stampFixup); stampWriter.WriteBytes(contentId.Stamp); Debug.Assert(stampWriter.RemainingBytes == 0); }
public BlobContentId Serialize(BlobBuilder builder) { // Define and serialize sections in two steps. // We need to know about all sections before serializing them. var serializedSections = SerializeSections(); // The positions and sizes of directories are calculated during section serialization. var directories = GetDirectories(); Blob stampFixup; WritePESignature(builder); WriteCoffHeader(builder, serializedSections, out stampFixup); WritePEHeader(builder, directories, serializedSections); WriteSectionHeaders(builder, serializedSections); builder.Align(Header.FileAlignment); foreach (var section in serializedSections) { builder.LinkSuffix(section.Builder); builder.Align(Header.FileAlignment); } var contentId = IdProvider(builder.GetBlobs()); // patch timestamp in COFF header: var stampWriter = new BlobWriter(stampFixup); stampWriter.WriteUInt32(contentId.Stamp); Debug.Assert(stampWriter.RemainingBytes == 0); return(contentId); }
private void WriteRuntimeStartupStub(BlobBuilder sectionBuilder, int importAddressTableRva, ulong baseAddress) { // entry point code, consisting of a jump indirect to _CorXXXMain if (Is32Bit) { // Write zeros (nops) to pad the entry point code so that the target address is aligned on a 4 byte boundary. // Note that the section is aligned to FileAlignment, which is at least 512, so we can align relatively to the start of the section. sectionBuilder.Align(4); sectionBuilder.WriteUInt16(0); sectionBuilder.WriteByte(0xff); sectionBuilder.WriteByte(0x25); //4 sectionBuilder.WriteUInt32((uint)importAddressTableRva + (uint)baseAddress); //8 } else { // Write zeros (nops) to pad the entry point code so that the target address is aligned on a 8 byte boundary. // Note that the section is aligned to FileAlignment, which is at least 512, so we can align relatively to the start of the section. sectionBuilder.Align(8); sectionBuilder.WriteUInt32(0); sectionBuilder.WriteUInt16(0); sectionBuilder.WriteByte(0xff); sectionBuilder.WriteByte(0x25); //8 sectionBuilder.WriteUInt64((ulong)importAddressTableRva + baseAddress); //16 } }
public void WriteData(BlobBuilder resourceWriter) { if (_fileReference == null) { try { using (Stream stream = _streamProvider()) { if (stream == null) { throw new InvalidOperationException(CodeAnalysisResources.ResourceStreamProviderShouldReturnNonNullStream); } var count = (int)(stream.Length - stream.Position); resourceWriter.WriteInt32(count); int bytesWritten = resourceWriter.TryWriteBytes(stream, count); if (bytesWritten != count) { throw new EndOfStreamException( string.Format(CultureInfo.CurrentUICulture, CodeAnalysisResources.ResourceStreamEndedUnexpectedly, bytesWritten, count)); } resourceWriter.Align(8); } } catch (Exception e) { throw new ResourceException(_name, e); } } }
internal static ExceptionRegionEncoder SerializeTableHeader(BlobBuilder builder, int exceptionRegionCount, bool hasSmallRegions) { Debug.Assert(exceptionRegionCount > 0); const byte EHTableFlag = 0x01; const byte FatFormatFlag = 0x40; bool hasSmallFormat = hasSmallRegions && IsSmallRegionCount(exceptionRegionCount); int dataSize = GetExceptionTableSize(exceptionRegionCount, hasSmallFormat); builder.Align(4); if (hasSmallFormat) { builder.WriteByte(EHTableFlag); builder.WriteByte(unchecked ((byte)dataSize)); builder.WriteInt16(0); } else { Debug.Assert(dataSize <= 0x00ffffff); builder.WriteByte(EHTableFlag | FatFormatFlag); builder.WriteByte(unchecked ((byte)dataSize)); builder.WriteUInt16(unchecked ((ushort)(dataSize >> 8))); } return(new ExceptionRegionEncoder(builder, hasSmallFormat)); }
/// <summary> /// Writes the method body to the given <see cref="BlobBuilder"/>. /// </summary> /// <param name="blob">The <see cref="BlobBuilder"/> representing the byte stream into which the /// method body should be written.</param> /// <param name="tokenMapping">A <see cref="TokenMapping"/> instance to use for replacing /// virtual tokens with their corresponding real tokens. If this is null, virtual tokens /// are not replaced.</param> public void writeToBlobBuilder(BlobBuilder blob, TokenMapping?tokenMapping = null) { if (m_useFatHeader) { blob.Align(4); } Span <byte> span = blob.ReserveBytes(m_totalLength).GetBytes(); writeToSpan(span, tokenMapping); }
public void WriteAlignPad() { var writer = new BlobBuilder(4); writer.WriteByte(0x01); writer.PadTo(2); writer.WriteByte(0x02); writer.Align(4); writer.Align(4); writer.WriteByte(0x03); writer.Align(4); writer.WriteByte(0x04); writer.WriteByte(0x05); writer.Align(8); writer.WriteByte(0x06); writer.Align(2); writer.Align(1); AssertEx.Equal(new byte[] { 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00 }, writer.ToArray()); }
// Adapted from: https://github.com/dotnet/corefx/blob/772a2486f2dd29f3a0401427a26da23e845a6e59/src/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/Encoding/MethodBodyStreamEncoder.cs#L222-L272 // private int SerializeHeader(int codeSize, int maxStack, int exceptionRegionCount, MethodBodyAttributes attributes, StandaloneSignatureHandle localVariablesSignature, bool hasDynamicStackAllocation) { const int TinyFormat = 2; const int FatFormat = 3; const int MoreSections = 8; const byte InitLocals = 0x10; var initLocals = (attributes & MethodBodyAttributes.InitLocals) != 0; var isTiny = codeSize < 64 && maxStack <= 8 && localVariablesSignature.IsNil && (!hasDynamicStackAllocation || !initLocals) && exceptionRegionCount == 0; int offset; if (isTiny) { offset = _builder.Count; _builder.WriteByte((byte)((codeSize << 2) | TinyFormat)); } else { _builder.Align(4); offset = _builder.Count; ushort flags = (3 << 12) | FatFormat; if (exceptionRegionCount > 0) { flags |= MoreSections; } if (initLocals) { flags |= InitLocals; } _builder.WriteUInt16((ushort)((int)attributes | flags)); _builder.WriteUInt16((ushort)maxStack); _builder.WriteInt32(codeSize); _builder.WriteInt32( localVariablesSignature.IsNil ? 0 : MetadataTokens.GetToken(localVariablesSignature)); } return(offset); }
/// <summary> /// Serializes .text section data into a specified <paramref name="builder"/>. /// </summary> /// <param name="builder">An empty builder to serialize section data to.</param> /// <param name="relativeVirtualAddess">Relative virtual address of the section within the containing PE file.</param> /// <param name="entryPointTokenOrRelativeVirtualAddress">Entry point token or RVA (<see cref="CorHeader.EntryPointTokenOrRelativeVirtualAddress"/>)</param> /// <param name="corFlags">COR Flags (<see cref="CorHeader.Flags"/>).</param> /// <param name="baseAddress">Base address of the PE image.</param> /// <param name="metadataBuilder"><see cref="BlobBuilder"/> containing metadata. Must be populated with data. Linked into the <paramref name="builder"/> and can't be expanded afterwards.</param> /// <param name="ilBuilder"><see cref="BlobBuilder"/> containing IL stream. Must be populated with data. Linked into the <paramref name="builder"/> and can't be expanded afterwards.</param> /// <param name="mappedFieldDataBuilder"><see cref="BlobBuilder"/> containing mapped field data. Must be populated with data. Linked into the <paramref name="builder"/> and can't be expanded afterwards.</param> /// <param name="resourceBuilder"><see cref="BlobBuilder"/> containing managed resource data. Must be populated with data. Linked into the <paramref name="builder"/> and can't be expanded afterwards.</param> /// <param name="debugTableBuilderOpt"><see cref="BlobBuilder"/> containing debug table data. Must be populated with data. Linked into the <paramref name="builder"/> and can't be expanded afterwards.</param> public void Serialize( BlobBuilder builder, int relativeVirtualAddess, int entryPointTokenOrRelativeVirtualAddress, CorFlags corFlags, ulong baseAddress, BlobBuilder metadataBuilder, BlobBuilder ilBuilder, BlobBuilder mappedFieldDataBuilder, BlobBuilder resourceBuilder, BlobBuilder debugTableBuilderOpt) { Debug.Assert(builder.Count == 0); Debug.Assert(metadataBuilder.Count == MetadataSize); Debug.Assert(metadataBuilder.Count % 4 == 0); Debug.Assert(ilBuilder.Count == ILStreamSize); Debug.Assert(mappedFieldDataBuilder.Count == MappedFieldDataSize); Debug.Assert(resourceBuilder.Count == ResourceDataSize); Debug.Assert(resourceBuilder.Count % 4 == 0); // TODO: avoid recalculation int importTableRva = GetImportTableDirectoryEntry(relativeVirtualAddess).RelativeVirtualAddress; int importAddressTableRva = GetImportAddressTableDirectoryEntry(relativeVirtualAddess).RelativeVirtualAddress; if (RequiresStartupStub) { WriteImportAddressTable(builder, importTableRva); } WriteCorHeader(builder, relativeVirtualAddess, entryPointTokenOrRelativeVirtualAddress, corFlags); // IL: ilBuilder.Align(4); builder.LinkSuffix(ilBuilder); // metadata: builder.LinkSuffix(metadataBuilder); // managed resources: builder.LinkSuffix(resourceBuilder); // strong name signature: builder.WriteBytes(0, StrongNameSignatureSize); if (debugTableBuilderOpt != null) { builder.LinkSuffix(debugTableBuilderOpt); } if (RequiresStartupStub) { WriteImportTable(builder, importTableRva, importAddressTableRva); WriteNameTable(builder); WriteRuntimeStartupStub(builder, importAddressTableRva, baseAddress); } // mapped field data: builder.LinkSuffix(mappedFieldDataBuilder); Debug.Assert(builder.Count == ComputeSizeOfTextSection()); }
/// <summary> /// Serializes .text section data into a specified <paramref name="builder"/>. /// </summary> /// <param name="builder">An empty builder to serialize section data to.</param> /// <param name="relativeVirtualAddess">Relative virtual address of the section within the containing PE file.</param> /// <param name="entryPointTokenOrRelativeVirtualAddress">Entry point token or RVA (<see cref="CorHeader.EntryPointTokenOrRelativeVirtualAddress"/>)</param> /// <param name="corFlags">COR Flags (<see cref="CorHeader.Flags"/>).</param> /// <param name="baseAddress">Base address of the PE image.</param> /// <param name="metadataBuilder"><see cref="BlobBuilder"/> containing metadata. Must be populated with data. Linked into the <paramref name="builder"/> and can't be expanded afterwards.</param> /// <param name="ilBuilder"><see cref="BlobBuilder"/> containing IL stream. Must be populated with data. Linked into the <paramref name="builder"/> and can't be expanded afterwards.</param> /// <param name="mappedFieldDataBuilderOpt"><see cref="BlobBuilder"/> containing mapped field data. Must be populated with data. Linked into the <paramref name="builder"/> and can't be expanded afterwards.</param> /// <param name="resourceBuilderOpt"><see cref="BlobBuilder"/> containing managed resource data. Must be populated with data. Linked into the <paramref name="builder"/> and can't be expanded afterwards.</param> /// <param name="debugDataBuilderOpt"><see cref="BlobBuilder"/> containing PE debug table and data. Must be populated with data. Linked into the <paramref name="builder"/> and can't be expanded afterwards.</param> /// <param name="strongNameSignature">Blob reserved in the <paramref name="builder"/> for strong name signature.</param> public void Serialize( BlobBuilder builder, int relativeVirtualAddess, int entryPointTokenOrRelativeVirtualAddress, CorFlags corFlags, ulong baseAddress, BlobBuilder metadataBuilder, BlobBuilder ilBuilder, BlobBuilder mappedFieldDataBuilderOpt, BlobBuilder resourceBuilderOpt, BlobBuilder debugDataBuilderOpt, out Blob strongNameSignature) { Debug.Assert(builder.Count == 0); Debug.Assert(metadataBuilder.Count == MetadataSize); Debug.Assert(metadataBuilder.Count % 4 == 0); Debug.Assert(ilBuilder.Count == ILStreamSize); Debug.Assert((mappedFieldDataBuilderOpt?.Count ?? 0) == MappedFieldDataSize); Debug.Assert((resourceBuilderOpt?.Count ?? 0) == ResourceDataSize); Debug.Assert((resourceBuilderOpt?.Count ?? 0) % 4 == 0); // TODO: avoid recalculation int importTableRva = GetImportTableDirectoryEntry(relativeVirtualAddess).RelativeVirtualAddress; int importAddressTableRva = GetImportAddressTableDirectoryEntry(relativeVirtualAddess).RelativeVirtualAddress; if (RequiresStartupStub) { WriteImportAddressTable(builder, importTableRva); } WriteCorHeader(builder, relativeVirtualAddess, entryPointTokenOrRelativeVirtualAddress, corFlags); // IL: ilBuilder.Align(4); builder.LinkSuffix(ilBuilder); // metadata: builder.LinkSuffix(metadataBuilder); // managed resources: if (resourceBuilderOpt != null) { builder.LinkSuffix(resourceBuilderOpt); } // strong name signature: strongNameSignature = builder.ReserveBytes(StrongNameSignatureSize); // The bytes are required to be 0 for the purpose of calculating hash of the PE content // when strong name signing. new BlobWriter(strongNameSignature).WriteBytes(0, StrongNameSignatureSize); // debug directory and data: if (debugDataBuilderOpt != null) { builder.LinkSuffix(debugDataBuilderOpt); } if (RequiresStartupStub) { WriteImportTable(builder, importTableRva, importAddressTableRva); WriteNameTable(builder); WriteRuntimeStartupStub(builder, importAddressTableRva, baseAddress); } // mapped field data: if (mappedFieldDataBuilderOpt != null) { builder.LinkSuffix(mappedFieldDataBuilderOpt); } Debug.Assert(builder.Count == ComputeSizeOfTextSection()); }
public static void SerializeWin32Resources(BlobBuilder builder, IEnumerable <IWin32Resource> theResources, int resourcesRva) { theResources = SortResources(theResources); Directory typeDirectory = new Directory(string.Empty, 0); Directory nameDirectory = null; Directory languageDirectory = null; int lastTypeID = int.MinValue; string lastTypeName = null; int lastID = int.MinValue; string lastName = null; uint sizeOfDirectoryTree = 16; //EDMAURER note that this list is assumed to be sorted lowest to highest //first by typeId, then by Id. foreach (IWin32Resource r in theResources) { bool typeDifferent = (r.TypeId < 0 && r.TypeName != lastTypeName) || r.TypeId > lastTypeID; if (typeDifferent) { lastTypeID = r.TypeId; lastTypeName = r.TypeName; if (lastTypeID < 0) { Debug.Assert(typeDirectory.NumberOfIdEntries == 0, "Not all Win32 resources with types encoded as strings precede those encoded as ints"); typeDirectory.NumberOfNamedEntries++; } else { typeDirectory.NumberOfIdEntries++; } sizeOfDirectoryTree += 24; typeDirectory.Entries.Add(nameDirectory = new Directory(lastTypeName, lastTypeID)); } if (typeDifferent || (r.Id < 0 && r.Name != lastName) || r.Id > lastID) { lastID = r.Id; lastName = r.Name; if (lastID < 0) { Debug.Assert(nameDirectory.NumberOfIdEntries == 0, "Not all Win32 resources with names encoded as strings precede those encoded as ints"); nameDirectory.NumberOfNamedEntries++; } else { nameDirectory.NumberOfIdEntries++; } sizeOfDirectoryTree += 24; nameDirectory.Entries.Add(languageDirectory = new Directory(lastName, lastID)); } languageDirectory.NumberOfIdEntries++; sizeOfDirectoryTree += 8; languageDirectory.Entries.Add(r); } var dataWriter = new BlobBuilder(); //'dataWriter' is where opaque resource data goes as well as strings that are used as type or name identifiers WriteDirectory(typeDirectory, builder, 0, 0, sizeOfDirectoryTree, resourcesRva, dataWriter); builder.LinkSuffix(dataWriter); builder.WriteByte(0); builder.Align(4); }
/// <summary> /// Serialize the export symbol table into the export section. /// </summary> /// <param name="location">RVA and file location of the .edata section</param> private BlobBuilder SerializeExportSection(SectionLocation sectionLocation) { _exportSymbols.MergeSort((es1, es2) => StringComparer.Ordinal.Compare(es1.Name, es2.Name)); BlobBuilder builder = new BlobBuilder(); int minOrdinal = int.MaxValue; int maxOrdinal = int.MinValue; // First, emit the name table and store the name RVA's for the individual export symbols // Also, record the ordinal range. foreach (ExportSymbol symbol in _exportSymbols) { symbol.NameRVAWhenPlaced = sectionLocation.RelativeVirtualAddress + builder.Count; builder.WriteUTF8(symbol.Name); builder.WriteByte(0); if (symbol.Ordinal < minOrdinal) { minOrdinal = symbol.Ordinal; } if (symbol.Ordinal > maxOrdinal) { maxOrdinal = symbol.Ordinal; } } // Emit the DLL name int dllNameRVA = sectionLocation.RelativeVirtualAddress + builder.Count; builder.WriteUTF8(_dllNameForExportDirectoryTable); builder.WriteByte(0); int[] addressTable = new int[maxOrdinal - minOrdinal + 1]; // Emit the name pointer table; it should be alphabetically sorted. // Also, we can now fill in the export address table as we've detected its size // in the previous pass. builder.Align(4); int namePointerTableRVA = sectionLocation.RelativeVirtualAddress + builder.Count; foreach (ExportSymbol symbol in _exportSymbols) { builder.WriteInt32(symbol.NameRVAWhenPlaced); SymbolTarget symbolTarget = _symbolMap[symbol.Symbol]; Section symbolSection = _sections[symbolTarget.SectionIndex]; Debug.Assert(symbolSection.RVAWhenPlaced != 0); addressTable[symbol.Ordinal - minOrdinal] = symbolSection.RVAWhenPlaced + symbolTarget.Offset; } // Emit the ordinal table int ordinalTableRVA = sectionLocation.RelativeVirtualAddress + builder.Count; foreach (ExportSymbol symbol in _exportSymbols) { builder.WriteUInt16((ushort)(symbol.Ordinal - minOrdinal)); } // Emit the address table builder.Align(4); int addressTableRVA = sectionLocation.RelativeVirtualAddress + builder.Count; foreach (int addressTableEntry in addressTable) { builder.WriteInt32(addressTableEntry); } // Emit the export directory table builder.Align(4); int exportDirectoryTableRVA = sectionLocation.RelativeVirtualAddress + builder.Count; // +0x00: reserved builder.WriteInt32(0); // +0x04: TODO: time/date stamp builder.WriteInt32(0); // +0x08: major version builder.WriteInt16(0); // +0x0A: minor version builder.WriteInt16(0); // +0x0C: DLL name RVA builder.WriteInt32(dllNameRVA); // +0x10: ordinal base builder.WriteInt32(minOrdinal); // +0x14: number of entries in the address table builder.WriteInt32(addressTable.Length); // +0x18: number of name pointers builder.WriteInt32(_exportSymbols.Count); // +0x1C: export address table RVA builder.WriteInt32(addressTableRVA); // +0x20: name pointer RVV builder.WriteInt32(namePointerTableRVA); // +0x24: ordinal table RVA builder.WriteInt32(ordinalTableRVA); int exportDirectorySize = sectionLocation.RelativeVirtualAddress + builder.Count - exportDirectoryTableRVA; _exportDirectoryEntry = new DirectoryEntry(relativeVirtualAddress: exportDirectoryTableRVA, size: exportDirectorySize); return(builder); }
internal void SerializeMetadataTables( BlobBuilder writer, MetadataSizes metadataSizes, int methodBodyStreamRva, int mappedFieldDataStreamRva) { int startPosition = writer.Count; this.SerializeTablesHeader(writer, metadataSizes); if (metadataSizes.IsPresent(TableIndex.Module)) { SerializeModuleTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.TypeRef)) { this.SerializeTypeRefTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.TypeDef)) { this.SerializeTypeDefTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.Field)) { this.SerializeFieldTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.MethodDef)) { this.SerializeMethodDefTable(writer, metadataSizes, methodBodyStreamRva); } if (metadataSizes.IsPresent(TableIndex.Param)) { this.SerializeParamTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.InterfaceImpl)) { this.SerializeInterfaceImplTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.MemberRef)) { this.SerializeMemberRefTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.Constant)) { this.SerializeConstantTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.CustomAttribute)) { this.SerializeCustomAttributeTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.FieldMarshal)) { this.SerializeFieldMarshalTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.DeclSecurity)) { this.SerializeDeclSecurityTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.ClassLayout)) { this.SerializeClassLayoutTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.FieldLayout)) { this.SerializeFieldLayoutTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.StandAloneSig)) { this.SerializeStandAloneSigTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.EventMap)) { this.SerializeEventMapTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.Event)) { this.SerializeEventTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.PropertyMap)) { this.SerializePropertyMapTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.Property)) { this.SerializePropertyTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.MethodSemantics)) { this.SerializeMethodSemanticsTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.MethodImpl)) { this.SerializeMethodImplTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.ModuleRef)) { this.SerializeModuleRefTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.TypeSpec)) { this.SerializeTypeSpecTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.ImplMap)) { this.SerializeImplMapTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.FieldRva)) { this.SerializeFieldRvaTable(writer, metadataSizes, mappedFieldDataStreamRva); } if (metadataSizes.IsPresent(TableIndex.EncLog)) { this.SerializeEncLogTable(writer); } if (metadataSizes.IsPresent(TableIndex.EncMap)) { this.SerializeEncMapTable(writer); } if (metadataSizes.IsPresent(TableIndex.Assembly)) { this.SerializeAssemblyTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.AssemblyRef)) { this.SerializeAssemblyRefTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.File)) { this.SerializeFileTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.ExportedType)) { this.SerializeExportedTypeTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.ManifestResource)) { this.SerializeManifestResourceTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.NestedClass)) { this.SerializeNestedClassTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.GenericParam)) { this.SerializeGenericParamTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.MethodSpec)) { this.SerializeMethodSpecTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.GenericParamConstraint)) { this.SerializeGenericParamConstraintTable(writer, metadataSizes); } // debug tables if (metadataSizes.IsPresent(TableIndex.Document)) { this.SerializeDocumentTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.MethodDebugInformation)) { this.SerializeMethodDebugInformationTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.LocalScope)) { this.SerializeLocalScopeTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.LocalVariable)) { this.SerializeLocalVariableTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.LocalConstant)) { this.SerializeLocalConstantTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.ImportScope)) { this.SerializeImportScopeTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.StateMachineMethod)) { this.SerializeStateMachineMethodTable(writer, metadataSizes); } if (metadataSizes.IsPresent(TableIndex.CustomDebugInformation)) { this.SerializeCustomDebugInformationTable(writer, metadataSizes); } writer.WriteByte(0); writer.Align(4); int endPosition = writer.Count; Debug.Assert(metadataSizes.MetadataTableStreamSize == endPosition - startPosition); }
private void WriteTextSection( Stream peStream, SectionHeader textSection, int importTableRva, int importAddressTableRva, int entryPointToken, BlobBuilder metadataWriter, BlobBuilder ilWriter, BlobBuilder mappedFieldDataWriter, BlobBuilder managedResourceWriter, MetadataSizes metadataSizes, ContentId nativePdbContentId, ContentId portablePdbContentId, out long metadataPosition) { // TODO: zero out all bytes: peStream.Position = textSection.PointerToRawData; if (_properties.RequiresStartupStub) { WriteImportAddressTable(peStream, importTableRva); } var corHeader = CreateCorHeader(metadataSizes, textSection.RelativeVirtualAddress, entryPointToken); WriteCorHeader(peStream, corHeader); // IL: ilWriter.Align(4); ilWriter.WriteContentTo(peStream); // metadata: metadataPosition = peStream.Position; Debug.Assert(metadataWriter.Count % 4 == 0); metadataWriter.WriteContentTo(peStream); // managed resources: Debug.Assert(managedResourceWriter.Count % 4 == 0); managedResourceWriter.WriteContentTo(peStream); // strong name signature: WriteSpaceForHash(peStream, metadataSizes.StrongNameSignatureSize); if (EmitPdb) { WriteDebugTable(peStream, textSection, nativePdbContentId, portablePdbContentId, metadataSizes); } if (_properties.RequiresStartupStub) { WriteImportTable(peStream, importTableRva, importAddressTableRva); WriteNameTable(peStream); WriteRuntimeStartupStub(peStream, importAddressTableRva); } // mapped field data: mappedFieldDataWriter.WriteContentTo(peStream); // TODO: zero out all bytes: int alignedPosition = textSection.PointerToRawData + textSection.SizeOfRawData; if (peStream.Position != alignedPosition) { peStream.Position = alignedPosition - 1; peStream.WriteByte(0); } }
internal static ExceptionRegionEncoder SerializeTableHeader(BlobBuilder builder, int exceptionRegionCount, bool hasSmallRegions) { Debug.Assert(exceptionRegionCount > 0); const byte EHTableFlag = 0x01; const byte FatFormatFlag = 0x40; bool hasSmallFormat = hasSmallRegions && IsSmallRegionCount(exceptionRegionCount); int dataSize = GetExceptionTableSize(exceptionRegionCount, hasSmallFormat); builder.Align(4); if (hasSmallFormat) { builder.WriteByte(EHTableFlag); builder.WriteByte(unchecked((byte)dataSize)); builder.WriteInt16(0); } else { Debug.Assert(dataSize <= 0x00ffffff); builder.WriteByte(EHTableFlag | FatFormatFlag); builder.WriteByte(unchecked((byte)dataSize)); builder.WriteUInt16(unchecked((ushort)(dataSize >> 8))); } return new ExceptionRegionEncoder(builder, hasSmallFormat); }
public static void SerializeWin32Resources(BlobBuilder builder, IEnumerable<IWin32Resource> theResources, int resourcesRva) { theResources = SortResources(theResources); Directory typeDirectory = new Directory(string.Empty, 0); Directory nameDirectory = null; Directory languageDirectory = null; int lastTypeID = int.MinValue; string lastTypeName = null; int lastID = int.MinValue; string lastName = null; uint sizeOfDirectoryTree = 16; //EDMAURER note that this list is assumed to be sorted lowest to highest //first by typeId, then by Id. foreach (IWin32Resource r in theResources) { bool typeDifferent = (r.TypeId < 0 && r.TypeName != lastTypeName) || r.TypeId > lastTypeID; if (typeDifferent) { lastTypeID = r.TypeId; lastTypeName = r.TypeName; if (lastTypeID < 0) { Debug.Assert(typeDirectory.NumberOfIdEntries == 0, "Not all Win32 resources with types encoded as strings precede those encoded as ints"); typeDirectory.NumberOfNamedEntries++; } else { typeDirectory.NumberOfIdEntries++; } sizeOfDirectoryTree += 24; typeDirectory.Entries.Add(nameDirectory = new Directory(lastTypeName, lastTypeID)); } if (typeDifferent || (r.Id < 0 && r.Name != lastName) || r.Id > lastID) { lastID = r.Id; lastName = r.Name; if (lastID < 0) { Debug.Assert(nameDirectory.NumberOfIdEntries == 0, "Not all Win32 resources with names encoded as strings precede those encoded as ints"); nameDirectory.NumberOfNamedEntries++; } else { nameDirectory.NumberOfIdEntries++; } sizeOfDirectoryTree += 24; nameDirectory.Entries.Add(languageDirectory = new Directory(lastName, lastID)); } languageDirectory.NumberOfIdEntries++; sizeOfDirectoryTree += 8; languageDirectory.Entries.Add(r); } var dataWriter = new BlobBuilder(); //'dataWriter' is where opaque resource data goes as well as strings that are used as type or name identifiers WriteDirectory(typeDirectory, builder, 0, 0, sizeOfDirectoryTree, resourcesRva, dataWriter); builder.LinkSuffix(dataWriter); builder.WriteByte(0); builder.Align(4); }
public static byte[] MakeRefasm(MetadataReader metaReader, PEReader peReader, LoggerBase logger, IImportFilter filter = null, bool makeMock = false, bool omitReferenceAssemblyAttr = false) { var metaBuilder = new MetadataBuilder(); var ilStream = new BlobBuilder(); ilStream.Align(4); var importer = new MetadataImporter(metaReader, metaBuilder, ilStream, logger) { MakeMock = makeMock, OmitReferenceAssemblyAttr = omitReferenceAssemblyAttr }; if (filter != null) { importer.Filter = filter; logger.Info?.Invoke("Using custom entity filter"); } else if (importer.IsInternalsVisible()) { importer.Filter = new AllowPublicAndInternals(); logger.Info?.Invoke("InternalsVisibleTo attributes found, using AllowPublicAndInternals entity filter"); } else { importer.Filter = new AllowPublic(); logger.Info?.Invoke("Using AllowPublic entity filter"); } var mvidBlob = importer.Import(); logger.Debug?.Invoke($"Building {(makeMock ? "mockup" : "reference")} assembly"); var metaRootBuilder = new MetadataRootBuilder(metaBuilder, metaReader.MetadataVersion, true); var peHeaderBuilder = new PEHeaderBuilder( Machine.I386, // override machine to force AnyCPU assembly peReader.PEHeaders.PEHeader.SectionAlignment, peReader.PEHeaders.PEHeader.FileAlignment, peReader.PEHeaders.PEHeader.ImageBase, peReader.PEHeaders.PEHeader.MajorLinkerVersion, peReader.PEHeaders.PEHeader.MinorLinkerVersion, peReader.PEHeaders.PEHeader.MajorOperatingSystemVersion, peReader.PEHeaders.PEHeader.MinorOperatingSystemVersion, peReader.PEHeaders.PEHeader.MajorImageVersion, peReader.PEHeaders.PEHeader.MinorImageVersion, peReader.PEHeaders.PEHeader.MajorSubsystemVersion, peReader.PEHeaders.PEHeader.MinorSubsystemVersion, peReader.PEHeaders.PEHeader.Subsystem, peReader.PEHeaders.PEHeader.DllCharacteristics, peReader.PEHeaders.CoffHeader.Characteristics, peReader.PEHeaders.PEHeader.SizeOfStackReserve, peReader.PEHeaders.PEHeader.SizeOfStackCommit, peReader.PEHeaders.PEHeader.SizeOfHeapReserve, peReader.PEHeaders.PEHeader.SizeOfHeapCommit ); var peBuilder = new ManagedPEBuilder(peHeaderBuilder, metaRootBuilder, ilStream, deterministicIdProvider: blobs => { var hasher = IncrementalHash.CreateHash(HashAlgorithmName.SHA256) ?? throw new Exception("Cannot create hasher"); foreach (var segment in blobs.Select(b => b.GetBytes())) { hasher.AppendData(segment.Array, segment.Offset, segment.Count); } return(BlobContentId.FromHash(hasher.GetHashAndReset())); }); var blobBuilder = new BlobBuilder(); var contentId = peBuilder.Serialize(blobBuilder); mvidBlob.CreateWriter().WriteGuid(contentId.Guid); return(blobBuilder.ToArray()); }