private static void WritePEImage( Stream peStream, MetadataBuilder metadataBuilder, BlobBuilder ilBuilder, MethodDefinitionHandle entryPointHandle, Blob mvidFixup = default(Blob), byte[] privateKeyOpt = null) { var peBuilder = new ManagedPEBuilder( entryPointHandle.IsNil ? PEHeaderBuilder.CreateLibraryHeader() : PEHeaderBuilder.CreateExecutableHeader(), new MetadataRootBuilder(metadataBuilder), ilBuilder, entryPoint: entryPointHandle, flags: CorFlags.ILOnly | (privateKeyOpt != null ? CorFlags.StrongNameSigned : 0), deterministicIdProvider: content => s_contentId); var peBlob = new BlobBuilder(); var contentId = peBuilder.Serialize(peBlob); if (!mvidFixup.IsDefault) { new BlobWriter(mvidFixup).WriteGuid(contentId.Guid); } if (privateKeyOpt != null) { peBuilder.Sign(peBlob, content => SigningUtilities.CalculateRsaSignature(content, privateKeyOpt)); } peBlob.WriteContentTo(peStream); }
public SerializedSection(BlobBuilder builder, string name, SectionCharacteristics characteristics, int relativeVirtualAddress, int sizeOfRawData, int pointerToRawData) { Name = name; Characteristics = characteristics; Builder = builder; RelativeVirtualAddress = relativeVirtualAddress; SizeOfRawData = sizeOfRawData; PointerToRawData = pointerToRawData; }
public void Empty() { var b = new DebugDirectoryBuilder(); var id = new BlobContentId(new Guid("3C88E66E-E0B9-4508-9290-11E0DB51A1C5"), 0x12345678); var blob = new BlobBuilder(); b.Serialize(blob, new SectionLocation(0x1000, 0x2000), 0x50); AssertEx.Equal(new byte[0], blob.ToArray()); }
public void AddCodeViewEntry2() { var b = new DebugDirectoryBuilder(); var id = new BlobContentId(new Guid("3C88E66E-E0B9-4508-9290-11E0DB51A1C5"), 0x12345678); b.AddCodeViewEntry("foo.pdb" + new string('\0', 260 - "foo.pdb".Length - 1), id, 0xABCD); var blob = new BlobBuilder(); b.Serialize(blob, new SectionLocation(0x1000, 0x2000), 0x50); var bytes = blob.ToArray(); AssertEx.Equal(new byte[] { 0x00, 0x00, 0x00, 0x00, // Characteristics 0x78, 0x56, 0x34, 0x12, // Stamp 0xCD, 0xAB, 0x4D, 0x50, // Version 0x02, 0x00, 0x00, 0x00, // Type 0x1C, 0x01, 0x00, 0x00, // SizeOfData 0x6C, 0x10, 0x00, 0x00, // AddressOfRawData 0x6C, 0x20, 0x00, 0x00, // PointerToRawData // data (byte)'R', (byte)'S', (byte)'D', (byte)'S', 0x6E, 0xE6, 0x88, 0x3C, 0xB9, 0xE0, 0x08, 0x45, 0x92, 0x90, 0x11, 0xE0, 0xDB, 0x51, 0xA1, 0xC5, // GUID 0x01, 0x00, 0x00, 0x00, // age (byte)'f', (byte)'o', (byte)'o', (byte)'.', (byte)'p', (byte)'d', (byte)'b', 0x00, // path // path padding: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, bytes); using (var pinned = new PinnedBlob(bytes)) { var actual = PEReader.ReadDebugDirectoryEntries(pinned.CreateReader(0, DebugDirectoryEntry.Size)); Assert.Equal(1, actual.Length); Assert.Equal(id.Stamp, actual[0].Stamp); Assert.Equal(0xABCD, actual[0].MajorVersion); Assert.Equal(0x504d, actual[0].MinorVersion); Assert.Equal(DebugDirectoryEntryType.CodeView, actual[0].Type); Assert.Equal(0x0000011c, actual[0].DataSize); Assert.Equal(0x0000106c, actual[0].DataRelativeVirtualAddress); Assert.Equal(0x0000206c, actual[0].DataPointer); } }
public void AddEmbeddedPortablePdbEntry_Args() { var bb = new BlobBuilder(); var builder = new DebugDirectoryBuilder(); Assert.Throws<ArgumentNullException>(() => builder.AddEmbeddedPortablePdbEntry(null, 0x0100)); Assert.Throws<ArgumentOutOfRangeException>(() => builder.AddEmbeddedPortablePdbEntry(bb, 0x0000)); Assert.Throws<ArgumentOutOfRangeException>(() => builder.AddEmbeddedPortablePdbEntry(bb, 0x00ff)); builder.AddEmbeddedPortablePdbEntry(bb, 0x0100); builder.AddEmbeddedPortablePdbEntry(bb, 0xffff); }
public void SerializeMetadata(BlobBuilder builder, Func<BlobBuilder, ContentId> idProvider, out ContentId contentId) { SerializeMetadataImpl(builder, methodBodyStreamRva: 0, mappedFieldDataStreamRva: 0); contentId = idProvider(builder); // fill in the id: var idWriter = new BlobWriter(_pdbIdBlob); idWriter.WriteBytes(contentId.Guid); idWriter.WriteBytes(contentId.Stamp); Debug.Assert(idWriter.RemainingBytes == 0); }
internal MethodBodyEncoder( BlobBuilder builder, ushort maxStack, int exceptionRegionCount, StandaloneSignatureHandle localVariablesSignature, MethodBodyAttributes attributes) { Builder = builder; _maxStack = maxStack; _localVariablesSignature = localVariablesSignature; _attributes = (byte)attributes; _exceptionRegionCount = exceptionRegionCount; }
public void BasicValidation() { using (var peStream = new MemoryStream()) { var ilBuilder = new BlobBuilder(); var metadataBuilder = new MetadataBuilder(); var entryPoint = BasicValidationEmit(metadataBuilder, ilBuilder); WritePEImage(peStream, metadataBuilder, ilBuilder, entryPoint); peStream.Position = 0; VerifyPE(peStream); } }
/// <summary> /// Serialized #Pdb stream. /// </summary> protected override void SerializeStandalonePdbStream(BlobBuilder builder) { int startPosition = builder.Position; // the id will be filled in later _pdbIdBlob = builder.ReserveBytes(MetadataSizes.PdbIdSize); builder.WriteInt32(_entryPoint.IsNil ? 0 : MetadataTokens.GetToken(_entryPoint)); builder.WriteUInt64(MetadataSizes.ExternalTablesMask); MetadataWriterUtilities.SerializeRowCounts(builder, MetadataSizes.ExternalRowCounts); int endPosition = builder.Position; Debug.Assert(MetadataSizes.CalculateStandalonePdbStreamSize() == endPosition - startPosition); }
public void AddEmbeddedPortablePdbEntry(BlobBuilder debugMetadata, ushort portablePdbVersion) { if (debugMetadata == null) { Throw.ArgumentNull(nameof(debugMetadata)); } int dataSize = WriteEmbeddedPortablePdbData(_dataBuilder, debugMetadata); AddEntry( type: DebugDirectoryEntryType.EmbeddedPortablePdb, version: PortablePdbVersions.DebugDirectoryEmbeddedVersion(portablePdbVersion), stamp: 0, dataSize: dataSize); }
private static void WritePEImage(Stream peStream, MetadataBuilder metadataBuilder, BlobBuilder ilBuilder, MethodDefinitionHandle entryPointHandle) { var mappedFieldDataBuilder = new BlobBuilder(); var managedResourceDataBuilder = new BlobBuilder(); var peBuilder = new PEBuilder( machine: 0, sectionAlignment: 0x2000, fileAlignment: 0x200, imageBase: 0x00400000, majorLinkerVersion: 0x30, // (what is ref.emit using?) minorLinkerVersion: 0, majorOperatingSystemVersion: 4, minorOperatingSystemVersion: 0, majorImageVersion: 0, minorImageVersion: 0, majorSubsystemVersion: 4, minorSubsystemVersion: 0, subsystem: Subsystem.WindowsCui, dllCharacteristics: DllCharacteristics.DynamicBase | DllCharacteristics.NxCompatible | DllCharacteristics.NoSeh | DllCharacteristics.TerminalServerAware, imageCharacteristics: entryPointHandle.IsNil ? Characteristics.Dll : Characteristics.ExecutableImage, sizeOfStackReserve: 0x00100000, sizeOfStackCommit: 0x1000, sizeOfHeapReserve: 0x00100000, sizeOfHeapCommit: 0x1000); var peDirectoriesBuilder = new PEDirectoriesBuilder(); peBuilder.AddManagedSections( peDirectoriesBuilder, new TypeSystemMetadataSerializer(metadataBuilder, "v4.0.30319", isMinimalDelta: false), ilBuilder, mappedFieldDataBuilder, managedResourceDataBuilder, nativeResourceSectionSerializer: null, strongNameSignatureSize: 0, entryPoint: entryPointHandle, pdbPathOpt: null, nativePdbContentId: default(ContentId), portablePdbContentId: default(ContentId), corFlags: CorFlags.ILOnly); var peBlob = new BlobBuilder(); ContentId peContentId; peBuilder.Serialize(peBlob, peDirectoriesBuilder, out peContentId); peBlob.WriteContentTo(peStream); }
public BlobBuilder(int capacity = DefaultChunkSize) { if (capacity < 0) { Throw.ArgumentOutOfRange(nameof(capacity)); } // the writer assumes little-endian architecture: if (!BitConverter.IsLittleEndian) { Throw.LitteEndianArchitectureRequired(); } _nextOrPrevious = this; _buffer = new byte[Math.Max(MinChunkSize, capacity)]; }
public static byte[] BuildPEWithDebugDirectory(DebugDirectoryBuilder debugDirectoryBuilder) { var peStream = new MemoryStream(); var ilBuilder = new BlobBuilder(); var metadataBuilder = new MetadataBuilder(); var peBuilder = new ManagedPEBuilder( PEHeaderBuilder.CreateLibraryHeader(), new MetadataRootBuilder(metadataBuilder), ilBuilder, debugDirectoryBuilder: debugDirectoryBuilder); var peImageBuilder = new BlobBuilder(); peBuilder.Serialize(peImageBuilder); return peImageBuilder.ToArray(); }
public ManagedPEBuilder( PEHeaderBuilder header, MetadataRootBuilder metadataRootBuilder, BlobBuilder ilStream, BlobBuilder mappedFieldData = null, BlobBuilder managedResources = null, ResourceSectionBuilder nativeResources = null, DebugDirectoryBuilder debugDirectoryBuilder = null, int strongNameSignatureSize = DefaultStrongNameSignatureSize, MethodDefinitionHandle entryPoint = default(MethodDefinitionHandle), CorFlags flags = CorFlags.ILOnly, Func<IEnumerable<Blob>, BlobContentId> deterministicIdProvider = null) : base(header, deterministicIdProvider) { if (header == null) { Throw.ArgumentNull(nameof(header)); } if (metadataRootBuilder == null) { Throw.ArgumentNull(nameof(metadataRootBuilder)); } if (ilStream == null) { Throw.ArgumentNull(nameof(ilStream)); } if (strongNameSignatureSize < 0) { Throw.ArgumentOutOfRange(nameof(strongNameSignatureSize)); } _metadataRootBuilder = metadataRootBuilder; _ilStream = ilStream; _mappedFieldDataOpt = mappedFieldData; _managedResourcesOpt = managedResources; _nativeResourcesOpt = nativeResources; _strongNameSignatureSize = strongNameSignatureSize; _entryPointOpt = entryPoint; _debugDirectoryBuilderOpt = debugDirectoryBuilder ?? CreateDefaultDebugDirectoryBuilder(); _corFlags = flags; _peDirectoriesBuilder = new PEDirectoriesBuilder(); }
public MethodBodiesEncoder(BlobBuilder builder = null) { if (builder == null) { builder = new BlobBuilder(); } // Fat methods are 4-byte aligned. We calculate the alignment relative to the start of the ILStream. // // See ECMA-335 paragraph 25.4.5, Method data section: // "At the next 4-byte boundary following the method body can be extra method data sections." if ((builder.Count % 4) != 0) { // TODO: error message throw new ArgumentException("Builder has to be aligned to 4 byte boundary", nameof(builder)); } Builder = builder; }
internal static void WriteCompressedInteger(BlobBuilder writer, uint value) { unchecked { if (value <= SingleByteCompressedIntegerMaxValue) { writer.WriteByte((byte)value); } else if (value <= TwoByteCompressedIntegerMaxValue) { writer.WriteUInt16BE((ushort)(0x8000 | value)); } else if (value <= MaxCompressedIntegerValue) { writer.WriteUInt32BE(0xc0000000 | value); } else { Throw.ValueArgumentOutOfRange(); } } }
private static int WriteCodeViewData(BlobBuilder builder, string pdbPath, Guid pdbGuid) { int start = builder.Count; builder.WriteByte((byte)'R'); builder.WriteByte((byte)'S'); builder.WriteByte((byte)'D'); builder.WriteByte((byte)'S'); // PDB id: builder.WriteGuid(pdbGuid); // age builder.WriteUInt32(1); // UTF-8 encoded zero-terminated path to PDB int pathStart = builder.Count; builder.WriteUTF8(pdbPath, allowUnpairedSurrogates: true); builder.WriteByte(0); return builder.Count - start; }
private static int WriteEmbeddedPortablePdbData(BlobBuilder builder, BlobBuilder debugMetadata) { int start = builder.Count; // header (signature, decompressed size): builder.WriteUInt32(PortablePdbVersions.DebugDirectoryEmbeddedSignature); builder.WriteInt32(debugMetadata.Count); // compressed data: var compressed = new MemoryStream(); using (var deflate = new DeflateStream(compressed, CompressionLevel.Optimal, leaveOpen: true)) { foreach (var blob in debugMetadata.GetBlobs()) { var segment = blob.GetBytes(); deflate.Write(segment.Array, segment.Offset, segment.Count); } } // TODO: avoid multiple copies: builder.WriteBytes(compressed.ToArray()); return builder.Count - start; }
private BlobBuilder SerializeRelocationSection(SectionLocation location) { var sectionBuilder = new BlobBuilder(); WriteRelocationSection(sectionBuilder, Header.Machine, _lazyEntryPointAddress); _peDirectoriesBuilder.BaseRelocationTable = new DirectoryEntry(location.RelativeVirtualAddress, sectionBuilder.Count); return sectionBuilder; }
private BlobBuilder SerializeResourceSection(SectionLocation location) { Debug.Assert(_nativeResourcesOpt != null); var sectionBuilder = new BlobBuilder(); _nativeResourcesOpt.Serialize(sectionBuilder, location); _peDirectoriesBuilder.ResourceTable = new DirectoryEntry(location.RelativeVirtualAddress, sectionBuilder.Count); return sectionBuilder; }
private BlobBuilder SerializeTextSection(SectionLocation location) { var sectionBuilder = new BlobBuilder(); var metadataBuilder = new BlobBuilder(); var metadataSizes = _metadataRootBuilder.Sizes; var textSection = new ManagedTextSection( imageCharacteristics: Header.ImageCharacteristics, machine: Header.Machine, ilStreamSize: _ilStream.Count, metadataSize: metadataSizes.MetadataSize, resourceDataSize: _managedResourcesOpt?.Count ?? 0, strongNameSignatureSize: _strongNameSignatureSize, debugDataSize: _debugDirectoryBuilderOpt?.Size ?? 0, mappedFieldDataSize: _mappedFieldDataOpt?.Count ?? 0); int methodBodyStreamRva = location.RelativeVirtualAddress + textSection.OffsetToILStream; int mappedFieldDataStreamRva = location.RelativeVirtualAddress + textSection.CalculateOffsetToMappedFieldDataStream(); _metadataRootBuilder.Serialize(metadataBuilder, methodBodyStreamRva, mappedFieldDataStreamRva); DirectoryEntry debugDirectoryEntry; BlobBuilder debugTableBuilderOpt; if (_debugDirectoryBuilderOpt != null) { int debugDirectoryOffset = textSection.ComputeOffsetToDebugDirectory(); debugTableBuilderOpt = new BlobBuilder(_debugDirectoryBuilderOpt.TableSize); _debugDirectoryBuilderOpt.Serialize(debugTableBuilderOpt, location, debugDirectoryOffset); // Only the size of the fixed part of the debug table goes here. debugDirectoryEntry = new DirectoryEntry( location.RelativeVirtualAddress + debugDirectoryOffset, _debugDirectoryBuilderOpt.TableSize); } else { debugTableBuilderOpt = null; debugDirectoryEntry = default(DirectoryEntry); } _lazyEntryPointAddress = textSection.GetEntryPointAddress(location.RelativeVirtualAddress); textSection.Serialize( sectionBuilder, location.RelativeVirtualAddress, _entryPointOpt.IsNil ? 0 : MetadataTokens.GetToken(_entryPointOpt), _corFlags, Header.ImageBase, metadataBuilder, _ilStream, _mappedFieldDataOpt, _managedResourcesOpt, debugTableBuilderOpt, out _lazyStrongNameSignature); _peDirectoriesBuilder.AddressOfEntryPoint = _lazyEntryPointAddress; _peDirectoriesBuilder.DebugTable = debugDirectoryEntry; _peDirectoriesBuilder.ImportAddressTable = textSection.GetImportAddressTableDirectoryEntry(location.RelativeVirtualAddress); _peDirectoriesBuilder.ImportTable = textSection.GetImportTableDirectoryEntry(location.RelativeVirtualAddress); _peDirectoriesBuilder.CorHeaderTable = textSection.GetCorHeaderDirectoryEntry(location.RelativeVirtualAddress); return sectionBuilder; }
internal void SerializeMetadataTables( BlobBuilder writer, MetadataSizes metadataSizes, int methodBodyStreamRva, int mappedFieldDataStreamRva) { int startPosition = writer.Position; 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.Position; Debug.Assert(metadataSizes.MetadataTableStreamSize == endPosition - startPosition); }
private void SerializeCustomDebugInformationTable(BlobBuilder writer, MetadataSizes metadataSizes) { // Note: we can sort the table at this point since no other table can reference its rows via RowId or CodedIndex (which would need updating otherwise). // OrderBy performs a stable sort, so multiple attributes with the same parent and kind will be sorted in the order they were added to the table. foreach (CustomDebugInformationRow row in _customDebugInformationTable.OrderBy((x, y) => { int result = (int)x.Parent - (int)y.Parent; return (result != 0) ? result : MetadataTokens.GetHeapOffset(x.Kind) - MetadataTokens.GetHeapOffset(y.Kind); })) { writer.WriteReference(row.Parent, metadataSizes.HasCustomDebugInformationSize); writer.WriteReference((uint)GetHeapOffset(row.Kind), metadataSizes.GuidIndexSize); writer.WriteReference((uint)GetHeapOffset(row.Value), metadataSizes.BlobIndexSize); } }
public void Sign(BlobBuilder peImage, Func<IEnumerable<Blob>, byte[]> signatureProvider) { if (peImage == null) { throw new ArgumentNullException(nameof(peImage)); } if (signatureProvider == null) { throw new ArgumentNullException(nameof(signatureProvider)); } var content = GetContentToSign(peImage); byte[] signature = signatureProvider(content); // signature may be shorter (the rest of the reserved space is padding): if (signature == null || signature.Length > _lazyStrongNameSignature.Length) { throw new InvalidOperationException(SR.SignatureProviderReturnedInvalidSignature); } // TODO: Native csc also calculates and fills checksum in the PE header // Using MapFileAndCheckSum() from imagehlp.dll. var writer = new BlobWriter(_lazyStrongNameSignature); writer.WriteBytes(signature); }
/// <summary> /// Compares the current content of this writer with another one. /// </summary> /// <exception cref="InvalidOperationException">Content is not available, the builder has been linked with another one.</exception> public bool ContentEquals(BlobBuilder other) { if (!IsHead) { Throw.InvalidOperationBuilderAlreadyLinked(); } if (ReferenceEquals(this, other)) { return(true); } if (other == null) { return(false); } if (!other.IsHead) { Throw.InvalidOperationBuilderAlreadyLinked(); } if (Count != other.Count) { return(false); } var leftEnumerator = GetChunks(); var rightEnumerator = other.GetChunks(); int leftStart = 0; int rightStart = 0; bool leftContinues = leftEnumerator.MoveNext(); bool rightContinues = rightEnumerator.MoveNext(); while (leftContinues && rightContinues) { Debug.Assert(leftStart == 0 || rightStart == 0); var left = leftEnumerator.Current; var right = rightEnumerator.Current; int minLength = Math.Min(left.Length - leftStart, right.Length - rightStart); if (!ByteSequenceComparer.Equals(left._buffer, leftStart, right._buffer, rightStart, minLength)) { return(false); } leftStart += minLength; rightStart += minLength; // nothing remains in left chunk to compare: if (leftStart == left.Length) { leftContinues = leftEnumerator.MoveNext(); leftStart = 0; } // nothing remains in left chunk to compare: if (rightStart == right.Length) { rightContinues = rightEnumerator.MoveNext(); rightStart = 0; } } return(leftContinues == rightContinues); }
// internal for testing internal void ClearChunk() { _length = 0; _previousLengthOrFrozenSuffixLengthDelta = 0; _nextOrPrevious = this; }
internal Blobs(BlobBuilder builder) { _chunks = new Chunks(builder); }
/// <summary> /// Serialize the Debug Table and Data. /// </summary> /// <param name="builder">Builder.</param> /// <param name="sectionLocation">The containing PE section location.</param> /// <param name="sectionOffset">Offset of the table within the containing section.</param> internal void Serialize(BlobBuilder builder, SectionLocation sectionLocation, int sectionOffset) { int dataOffset = sectionOffset + TableSize; foreach (var entry in _entries) { int addressOfRawData; int pointerToRawData; if (entry.DataSize > 0) { addressOfRawData = sectionLocation.RelativeVirtualAddress + dataOffset; pointerToRawData = sectionLocation.PointerToRawData + dataOffset; } else { addressOfRawData = 0; pointerToRawData = 0; } builder.WriteUInt32(0); // characteristics, always 0 builder.WriteUInt32(entry.Stamp); builder.WriteUInt32(entry.Version); builder.WriteInt32((int)entry.Type); builder.WriteInt32(entry.DataSize); builder.WriteInt32(addressOfRawData); builder.WriteInt32(pointerToRawData); dataOffset += entry.DataSize; } builder.LinkSuffix(_dataBuilder); }
private static void WriteRelocationSection(BlobBuilder builder, Machine machine, int entryPointAddress) { Debug.Assert(builder.Count == 0); builder.WriteUInt32((((uint)entryPointAddress + 2) / 0x1000) * 0x1000); builder.WriteUInt32((machine == Machine.IA64) ? 14u : 12u); uint offsetWithinPage = ((uint)entryPointAddress + 2) % 0x1000; uint relocType = (machine == Machine.Amd64 || machine == Machine.IA64) ? 10u : 3u; ushort s = (ushort)((relocType << 12) | offsetWithinPage); builder.WriteUInt16(s); if (machine == Machine.IA64) { builder.WriteUInt32(relocType << 12); } builder.WriteUInt16(0); // next chunk's RVA }
private IEnumerable<Blob> GetContentToSign(BlobBuilder peImage) { // Signed content includes // - PE header without its alignment padding // - all sections including their alignment padding and excluding strong name signature blob int remainingHeader = Header.ComputeSizeOfPeHeaders(GetSections().Length); foreach (var blob in peImage.GetBlobs()) { if (remainingHeader > 0) { int length = Math.Min(remainingHeader, blob.Length); yield return new Blob(blob.Buffer, blob.Start, length); remainingHeader -= length; } else if (blob.Buffer == _lazyStrongNameSignature.Buffer) { yield return new Blob(blob.Buffer, blob.Start, _lazyStrongNameSignature.Start - blob.Start); yield return new Blob(blob.Buffer, _lazyStrongNameSignature.Start + _lazyStrongNameSignature.Length, blob.Length - _lazyStrongNameSignature.Length); } else { yield return new Blob(blob.Buffer, blob.Start, blob.Length); } } }
private void SerializeImportScopeTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (var row in _importScopeTable) { writer.WriteReference(row.Parent, metadataSizes.ImportScopeIndexSize); writer.WriteReference((uint)GetHeapOffset(row.Imports), metadataSizes.BlobIndexSize); } }
/// <exception cref="ArgumentNullException"><paramref name="suffix"/> is null.</exception> /// <exception cref="InvalidOperationException">Builder is not writable, it has been linked with another one.</exception> public void LinkSuffix(BlobBuilder suffix) { if (suffix is null) { Throw.ArgumentNull(nameof(suffix)); } // TODO: consider copying data from right to left while there is space if (!IsHead || !suffix.IsHead) { Throw.InvalidOperationBuilderAlreadyLinked(); } // avoid chaining empty chunks: if (suffix.Count == 0) { return; } bool isEmpty = Count == 0; // swap buffers of the heads: var suffixBuffer = suffix._buffer; uint suffixLength = suffix._length; int suffixPreviousLength = suffix.PreviousLength; int oldSuffixLength = suffix.Length; suffix._buffer = _buffer; suffix._length = FrozenLength; // suffix is not a head anymore _buffer = suffixBuffer; _length = suffixLength; PreviousLength += suffix.Length + suffixPreviousLength; // Update the _previousLength of the suffix so that suffix.Count = suffix._previousLength + suffix.Length doesn't change. // Note that the resulting previous length might be negative. // The value is not used, other than for calculating the value of Count property. suffix._previousLengthOrFrozenSuffixLengthDelta = suffixPreviousLength + oldSuffixLength - suffix.Length; if (!isEmpty) { // First and last chunks: // // [First]->[]->[Last] <- [this] [SuffixFirst]->[]->[SuffixLast] <- [suffix] // ^___________| ^_________________| // // Degenerate cases: // this == First == Last and/or suffix == SuffixFirst == SuffixLast. var first = FirstChunk; var suffixFirst = suffix.FirstChunk; var last = _nextOrPrevious; var suffixLast = suffix._nextOrPrevious; // Relink like so: // [First]->[]->[Last] -> [suffix] -> [SuffixFirst]->[]->[SuffixLast] <- [this] // ^_______________________________________________________| _nextOrPrevious = suffixLast; suffix._nextOrPrevious = (suffixFirst != suffix) ? suffixFirst : (first != this) ? first : suffix; if (last != this) { last._nextOrPrevious = suffix; } if (suffixLast != suffix) { suffixLast._nextOrPrevious = (first != this) ? first : suffix; } } CheckInvariants(); suffix.CheckInvariants(); }
private void SerializeStateMachineMethodTable(BlobBuilder writer, MetadataSizes metadataSizes) { #if DEBUG for (int i = 1; i < _stateMachineMethodTable.Count; i++) { Debug.Assert(_stateMachineMethodTable[i - 1].MoveNextMethod < _stateMachineMethodTable[i].MoveNextMethod); } #endif foreach (var row in _stateMachineMethodTable) { writer.WriteReference(row.MoveNextMethod, metadataSizes.MethodDefIndexSize); writer.WriteReference(row.KickoffMethod, metadataSizes.MethodDefIndexSize); } }
public DebugDirectoryBuilder() { _entries = new List<Entry>(2); _dataBuilder = new BlobBuilder(); }
internal static void WriteConstant(BlobBuilder writer, object?value) { if (value == null) { // The encoding of Type for the nullref value for FieldInit is ELEMENT_TYPE_CLASS with a Value of a 32-bit. writer.WriteUInt32(0); return; } var type = value.GetType(); if (type.GetTypeInfo().IsEnum) { type = Enum.GetUnderlyingType(type); } if (type == typeof(bool)) { writer.WriteBoolean((bool)value); } else if (type == typeof(int)) { writer.WriteInt32((int)value); } else if (type == typeof(string)) { writer.WriteUTF16((string)value); } else if (type == typeof(byte)) { writer.WriteByte((byte)value); } else if (type == typeof(char)) { writer.WriteUInt16((char)value); } else if (type == typeof(double)) { writer.WriteDouble((double)value); } else if (type == typeof(short)) { writer.WriteInt16((short)value); } else if (type == typeof(long)) { writer.WriteInt64((long)value); } else if (type == typeof(sbyte)) { writer.WriteSByte((sbyte)value); } else if (type == typeof(float)) { writer.WriteSingle((float)value); } else if (type == typeof(ushort)) { writer.WriteUInt16((ushort)value); } else if (type == typeof(uint)) { writer.WriteUInt32((uint)value); } else if (type == typeof(ulong)) { writer.WriteUInt64((ulong)value); } else { throw new ArgumentException(SR.Format(SR.InvalidConstantValueOfType, type)); } }