/// <summary> /// Constructs a <see cref="SourceText"/> from stream content. /// </summary> /// <param name="stream">Stream.</param> /// <param name="encoding"> /// Data encoding to use if the stream doesn't start with Byte Order Mark specifying the encoding. /// <see cref="Encoding.UTF8"/> if not specified. /// </param> /// <exception cref="ArgumentNullException"><paramref name="stream"/> is null.</exception> /// <exception cref="ArgumentException"><paramref name="stream"/> doesn't support reading or seeking.</exception> /// <exception cref="IOException">An I/O error occurs.</exception> /// <remarks>Reads from the beginning of the stream. Leaves the stream open.</remarks> public static SourceText From(Stream stream, Encoding encoding = null) { if (stream == null) { throw new ArgumentNullException("stream"); } if (!stream.CanRead || !stream.CanSeek) { throw new ArgumentException(CodeAnalysisResources.StreamMustSupportReadAndSeek, "stream"); } encoding = encoding ?? Encoding.UTF8; // TODO: unify encoding detection with EncodedStringText stream.Seek(0, SeekOrigin.Begin); string text; using (var reader = new StreamReader(stream, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true)) { text = reader.ReadToEnd(); } return(new StringText(text, encoding, CryptographicHashProvider.ComputeSha1(stream))); }
private EmbeddedSourceTextInfo?ResolveEmbeddedSource( DocumentHandle document, SourceTextInfo sourceTextInfo ) { byte[] bytes = ( from handle in PdbReader.GetCustomDebugInformation(document) let cdi = PdbReader.GetCustomDebugInformation(handle) where PdbReader.GetGuid(cdi.Kind) == EmbeddedSourceGuid select PdbReader.GetBlobBytes(cdi.Value) ).SingleOrDefault(); if (bytes is null) { return(null); } int uncompressedSize = BitConverter.ToInt32(bytes, 0); var stream = new MemoryStream(bytes, sizeof(int), bytes.Length - sizeof(int)); byte[]? compressedHash = null; if (uncompressedSize != 0) { using var algorithm = CryptographicHashProvider.TryGetAlgorithm(sourceTextInfo.HashAlgorithm) ?? throw new InvalidOperationException(); compressedHash = algorithm.ComputeHash(bytes); var decompressed = new MemoryStream(uncompressedSize); using (var deflater = new DeflateStream(stream, CompressionMode.Decompress)) { deflater.CopyTo(decompressed); } if (decompressed.Length != uncompressedSize) { throw new InvalidDataException(); } stream = decompressed; } using (stream) { // todo: IVT and EncodedStringText.Create? var embeddedText = SourceText.From( stream, encoding: sourceTextInfo.SourceTextEncoding, checksumAlgorithm: sourceTextInfo.HashAlgorithm, canBeEmbedded: true ); return(new EmbeddedSourceTextInfo( sourceTextInfo, embeddedText, compressedHash?.ToImmutableArray() ?? ImmutableArray <byte> .Empty )); } }
private static ImmutableArray <byte> CalculateChecksum(byte[] buffer, int offset, int count, SourceHashAlgorithm algorithmId) { using (var algorithm = CryptographicHashProvider.TryGetAlgorithm(algorithmId)) { Debug.Assert(algorithm != null); return(ImmutableArray.Create(algorithm.ComputeHash(buffer, offset, count))); } }
private static ImmutableArray <byte> CalculateChecksum(Stream stream, SourceHashAlgorithm algorithmId) { using (var algorithm = CryptographicHashProvider.TryGetAlgorithm(algorithmId)) { Debug.Assert(algorithm != null); stream.Seek(0, SeekOrigin.Begin); return(ImmutableArray.Create(algorithm.ComputeHash(stream))); } }
public void FromStream_CheckSum_DefaultEncoding() { var bytes = Encoding.UTF8.GetBytes("\u1234"); var source = SourceText.From(new MemoryStream(bytes)); Assert.Equal("\u1234", source.ToString()); var checksum = source.GetChecksum(); AssertEx.Equal(CryptographicHashProvider.ComputeSha1(bytes), checksum); }
public void FromStream_CheckSum_BOM() { var bytes = new byte[] { 0xef, 0xbb, 0xbf, 0x61, 0x62, 0x63 }; var source = SourceText.From(new MemoryStream(bytes), Encoding.ASCII); Assert.Equal("abc", source.ToString()); var checksum = source.GetChecksum(); AssertEx.Equal(CryptographicHashProvider.ComputeSha1(bytes), checksum); }
internal static ImmutableArray <byte> CalculateChecksum(Stream stream, SourceHashAlgorithm algorithmId) { using (System.Security.Cryptography.HashAlgorithm algorithm = CryptographicHashProvider.TryGetAlgorithm(algorithmId)) { Debug.Assert(algorithm != null); if (stream.CanSeek) { stream.Seek(0, SeekOrigin.Begin); } return(ImmutableArray.Create(algorithm.ComputeHash(stream))); } }
public sealed override IEnumerable <Cci.IFileReference> GetFiles(EmitContext context) { if (!context.IsRefAssembly) { return(getFiles(ref _lazyFiles)); } return(getFiles(ref _lazyFilesWithoutManifestResources)); ImmutableArray <Cci.IFileReference> getFiles(ref ImmutableArray <Cci.IFileReference> lazyFiles) { if (lazyFiles.IsDefault) { var builder = ArrayBuilder <Cci.IFileReference> .GetInstance(); try { var modules = _sourceAssembly.Modules; for (int i = 1; i < modules.Length; i++) { builder.Add((Cci.IFileReference)Translate(modules[i], context.Diagnostics)); } if (!context.IsRefAssembly) { // resources are not emitted into ref assemblies foreach (ResourceDescription resource in ManifestResources) { if (!resource.IsEmbedded) { builder.Add(resource); } } } // Dev12 compilers don't report ERR_CryptoHashFailed if there are no files to be hashed. if (ImmutableInterlocked.InterlockedInitialize(ref lazyFiles, builder.ToImmutable()) && lazyFiles.Length > 0) { if (!CryptographicHashProvider.IsSupportedAlgorithm(_sourceAssembly.HashAlgorithm)) { context.Diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(ErrorCode.ERR_CryptoHashFailed), NoLocation.Singleton)); } } } finally { builder.Free(); } } return(lazyFiles); } }
protected SourceText(ImmutableArray <byte> checksum = default(ImmutableArray <byte>), SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1, SourceTextContainer container = null) { ValidateChecksumAlgorithm(checksumAlgorithm); if (!checksum.IsDefault && checksum.Length != CryptographicHashProvider.GetHashSize(checksumAlgorithm)) { throw new ArgumentException(CodeAnalysisResources.InvalidHash, nameof(checksum)); } _checksumAlgorithm = checksumAlgorithm; _lazyChecksum = checksum; _lazyContainer = container; }
/// <summary> /// Loads the assembly portability policy from the given path using the CLR API. /// If any problems are encountered by the CLR, the errors are passed through via CLR exception. /// Can throw IO exceptions if any are encountered during file access. /// </summary> /// <param name="appConfigPath">Absolute path to the config file.</param> /// <returns></returns> public static FusionAssemblyPortabilityPolicy LoadFromFile(string appConfigPath) { Debug.Assert(PathUtilities.IsAbsolute(appConfigPath)); IntPtr asmConfigCookie; // May throw CLR exception CreateAssemblyConfigCookie(appConfigPath, out asmConfigCookie); var hash = CryptographicHashProvider.ComputeSha1(File.ReadAllBytes(appConfigPath)); return(new FusionAssemblyPortabilityPolicy(asmConfigCookie, hash)); }
internal static string GenerateDataFieldName(ImmutableArray <byte> data) { var hash = CryptographicHashProvider.ComputeSha1(data); char[] c = new char[hash.Length * 2]; int i = 0; foreach (var b in hash) { c[i++] = Hexchar(b >> 4); c[i++] = Hexchar(b & 0xF); } return(new string(c)); }
public void FromStream_CheckSum_NoBOM() { // Note: The 0x95 is outside the ASCII range, so a question mark will // be substituted in decoded text. Note, however, that the checksum // should be derived from the original input. var bytes = new byte[] { 0x61, 0x62, 0x95 }; var source = SourceText.From(new MemoryStream(bytes), Encoding.ASCII); Assert.Equal("ab?", source.ToString()); var checksum = source.GetChecksum(); AssertEx.Equal(CryptographicHashProvider.ComputeSha1(bytes), checksum); }
internal static string GenerateDataFieldName(ImmutableArray <byte> data) { // TODO: replace SHA1 with non-crypto alg: https://github.com/dotnet/roslyn/issues/24737 var hash = CryptographicHashProvider.ComputeSha1(data); char[] c = new char[hash.Length * 2]; int i = 0; foreach (var b in hash) { c[i++] = Hexchar(b >> 4); c[i++] = Hexchar(b & 0xF); } return(new string(c)); }
IEnumerable <Cci.IFileReference> Cci.IAssembly.GetFiles(Microsoft.CodeAnalysis.Emit.Context context) { if (lazyFiles.IsDefault) { var builder = ArrayBuilder <Cci.IFileReference> .GetInstance(); try { var modules = sourceAssembly.Modules; for (int i = 1; i < modules.Length; i++) { builder.Add((Cci.IFileReference)Translate(modules[i], context.Diagnostics)); } foreach (ResourceDescription resource in ManifestResources) { if (!resource.IsEmbedded) { builder.Add(resource); } } // Dev12 compilers don't report ERR_CryptoHashFailed if there are no files to be hashed. if (ImmutableInterlocked.InterlockedInitialize(ref lazyFiles, builder.ToImmutable()) && lazyFiles.Length > 0) { if (!CryptographicHashProvider.IsSupportedAlgorithm(sourceAssembly.AssemblyHashAlgorithm)) { context.Diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(ErrorCode.ERR_CryptoHashFailed), NoLocation.Singleton)); } } } finally { builder.Free(); } } return(lazyFiles); }
internal static bool WritePeToStream( EmitContext context, CommonMessageProvider messageProvider, Func <Stream> getPeStream, Func <Stream> getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt, string pdbPathOpt, bool metadataOnly, bool isDeterministic, bool emitTestCoverageData, RSAParameters?privateKeyOpt, CancellationToken cancellationToken) { // If PDB writer is given, we have to have PDB path. Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null); var mdWriter = FullMetadataWriter.Create(context, messageProvider, metadataOnly, isDeterministic, emitTestCoverageData, getPortablePdbStreamOpt != null, cancellationToken); var properties = context.Module.SerializationProperties; nativePdbWriterOpt?.SetMetadataEmitter(mdWriter); // Since we are producing a full assembly, we should not have a module version ID // imposed ahead-of time. Instead we will compute a deterministic module version ID // based on the contents of the generated stream. Debug.Assert(properties.PersistentIdentifier == default(Guid)); var ilBuilder = new BlobBuilder(32 * 1024); var mappedFieldDataBuilder = new BlobBuilder(); var managedResourceBuilder = new BlobBuilder(1024); Blob mvidFixup, mvidStringFixup; mdWriter.BuildMetadataAndIL( nativePdbWriterOpt, ilBuilder, mappedFieldDataBuilder, managedResourceBuilder, out mvidFixup, out mvidStringFixup); MethodDefinitionHandle entryPointHandle; MethodDefinitionHandle debugEntryPointHandle; mdWriter.GetEntryPoints(out entryPointHandle, out debugEntryPointHandle); if (!debugEntryPointHandle.IsNil) { nativePdbWriterOpt?.SetEntryPoint(MetadataTokens.GetToken(debugEntryPointHandle)); } if (nativePdbWriterOpt != null) { if (context.Module.SourceLinkStreamOpt != null) { nativePdbWriterOpt.EmbedSourceLink(context.Module.SourceLinkStreamOpt); } if (mdWriter.Module.OutputKind == OutputKind.WindowsRuntimeMetadata) { // Dev12: If compiling to winmdobj, we need to add to PDB source spans of // all types and members for better error reporting by WinMDExp. nativePdbWriterOpt.WriteDefinitionLocations(mdWriter.Module.GetSymbolToLocationMap()); } else { #if DEBUG // validate that all definitions are writable // if same scenario would happen in an winmdobj project nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap()); #endif } nativePdbWriterOpt.WriteRemainingEmbeddedDocuments(mdWriter.Module.DebugDocumentsBuilder.EmbeddedDocuments); } Stream peStream = getPeStream(); if (peStream == null) { return(false); } BlobContentId pdbContentId = nativePdbWriterOpt?.GetContentId() ?? default; // the writer shall not be used after this point for writing: nativePdbWriterOpt = null; ushort portablePdbVersion = 0; var metadataRootBuilder = mdWriter.GetRootBuilder(); var peHeaderBuilder = new PEHeaderBuilder( machine: properties.Machine, sectionAlignment: properties.SectionAlignment, fileAlignment: properties.FileAlignment, imageBase: properties.BaseAddress, majorLinkerVersion: properties.LinkerMajorVersion, minorLinkerVersion: properties.LinkerMinorVersion, majorOperatingSystemVersion: 4, minorOperatingSystemVersion: 0, majorImageVersion: 0, minorImageVersion: 0, majorSubsystemVersion: properties.MajorSubsystemVersion, minorSubsystemVersion: properties.MinorSubsystemVersion, subsystem: properties.Subsystem, dllCharacteristics: properties.DllCharacteristics, imageCharacteristics: properties.ImageCharacteristics, sizeOfStackReserve: properties.SizeOfStackReserve, sizeOfStackCommit: properties.SizeOfStackCommit, sizeOfHeapReserve: properties.SizeOfHeapReserve, sizeOfHeapCommit: properties.SizeOfHeapCommit); // TODO: replace SHA1 with non-crypto alg: https://github.com/dotnet/roslyn/issues/24737 var peIdProvider = isDeterministic ? new Func <IEnumerable <Blob>, BlobContentId>(content => BlobContentId.FromHash(CryptographicHashProvider.ComputeHash(HashAlgorithmName.SHA1, content))) : null; // We need to calculate the PDB checksum, so we may as well use the calculated hash for PDB ID regardless of whether deterministic build is requested. var portablePdbContentHash = default(ImmutableArray <byte>); BlobBuilder portablePdbToEmbed = null; if (mdWriter.EmitPortableDebugMetadata) { mdWriter.AddRemainingEmbeddedDocuments(mdWriter.Module.DebugDocumentsBuilder.EmbeddedDocuments); // The algorithm must be specified for deterministic builds (checked earlier). Debug.Assert(!isDeterministic || context.Module.PdbChecksumAlgorithm.Name != null); var portablePdbIdProvider = (context.Module.PdbChecksumAlgorithm.Name != null) ? new Func <IEnumerable <Blob>, BlobContentId>(content => BlobContentId.FromHash(portablePdbContentHash = CryptographicHashProvider.ComputeHash(context.Module.PdbChecksumAlgorithm, content))) : null; var portablePdbBlob = new BlobBuilder(); var portablePdbBuilder = mdWriter.GetPortablePdbBuilder(metadataRootBuilder.Sizes.RowCounts, debugEntryPointHandle, portablePdbIdProvider); pdbContentId = portablePdbBuilder.Serialize(portablePdbBlob); portablePdbVersion = portablePdbBuilder.FormatVersion; if (getPortablePdbStreamOpt == null) { // embed to debug directory: portablePdbToEmbed = portablePdbBlob; } else { // write to Portable PDB stream: Stream portablePdbStream = getPortablePdbStreamOpt(); if (portablePdbStream != null) { try { portablePdbBlob.WriteContentTo(portablePdbStream); } catch (Exception e) when(!(e is OperationCanceledException)) { throw new SymUnmanagedWriterException(e.Message, e); } } } } DebugDirectoryBuilder debugDirectoryBuilder; if (pdbPathOpt != null || isDeterministic || portablePdbToEmbed != null) { debugDirectoryBuilder = new DebugDirectoryBuilder(); if (pdbPathOpt != null) { string paddedPath = isDeterministic ? pdbPathOpt : PadPdbPath(pdbPathOpt); debugDirectoryBuilder.AddCodeViewEntry(paddedPath, pdbContentId, portablePdbVersion); if (!portablePdbContentHash.IsDefault) { // Emit PDB Checksum entry for Portable and Embedded PDBs. The checksum is not as useful when the PDB is embedded, // however it allows the client to efficiently validate a standalone Portable PDB that // has been extracted from Embedded PDB and placed next to the PE file. debugDirectoryBuilder.AddPdbChecksumEntry(context.Module.PdbChecksumAlgorithm.Name, portablePdbContentHash); } } if (isDeterministic) { debugDirectoryBuilder.AddReproducibleEntry(); } if (portablePdbToEmbed != null) { debugDirectoryBuilder.AddEmbeddedPortablePdbEntry(portablePdbToEmbed, portablePdbVersion); } } else { debugDirectoryBuilder = null; } var strongNameProvider = context.Module.CommonCompilation.Options.StrongNameProvider; var corFlags = properties.CorFlags; var peBuilder = new ExtendedPEBuilder( peHeaderBuilder, metadataRootBuilder, ilBuilder, mappedFieldDataBuilder, managedResourceBuilder, CreateNativeResourceSectionSerializer(context.Module), debugDirectoryBuilder, CalculateStrongNameSignatureSize(context.Module, privateKeyOpt), entryPointHandle, corFlags, peIdProvider, metadataOnly && !context.IncludePrivateMembers); var peBlob = new BlobBuilder(); var peContentId = peBuilder.Serialize(peBlob, out Blob mvidSectionFixup); PatchModuleVersionIds(mvidFixup, mvidSectionFixup, mvidStringFixup, peContentId.Guid); if (privateKeyOpt != null && corFlags.HasFlag(CorFlags.StrongNameSigned)) { Debug.Assert(strongNameProvider.Capability == SigningCapability.SignsPeBuilder); strongNameProvider.SignPeBuilder(peBuilder, peBlob, privateKeyOpt.Value); } try { peBlob.WriteContentTo(peStream); } catch (Exception e) when(!(e is OperationCanceledException)) { throw new PeWritingException(e); } return(true); }
public static bool WritePeToStream( EmitContext context, CommonMessageProvider messageProvider, Func <Stream> getPeStream, Func <Stream> getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt, string pdbPathOpt, bool allowMissingMethodBodies, bool isDeterministic, CancellationToken cancellationToken) { // If PDB writer is given, we have to have PDB path. Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null); var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, isDeterministic, getPortablePdbStreamOpt != null, cancellationToken); var properties = context.Module.Properties; nativePdbWriterOpt?.SetMetadataEmitter(mdWriter); // Since we are producing a full assembly, we should not have a module version ID // imposed ahead-of time. Instead we will compute a deterministic module version ID // based on the contents of the generated stream. Debug.Assert(properties.PersistentIdentifier == default(Guid)); var ilBuilder = new BlobBuilder(32 * 1024); var mappedFieldDataBuilder = new BlobBuilder(); var managedResourceBuilder = new BlobBuilder(1024); Blob mvidFixup; mdWriter.BuildMetadataAndIL( nativePdbWriterOpt, ilBuilder, mappedFieldDataBuilder, managedResourceBuilder, out mvidFixup); MethodDefinitionHandle entryPointHandle; MethodDefinitionHandle debugEntryPointHandle; mdWriter.GetEntryPoints(out entryPointHandle, out debugEntryPointHandle); if (!debugEntryPointHandle.IsNil) { nativePdbWriterOpt?.SetEntryPoint((uint)MetadataTokens.GetToken(debugEntryPointHandle)); } if (nativePdbWriterOpt != null) { var assembly = mdWriter.Module.AsAssembly; if (assembly != null && assembly.Kind == OutputKind.WindowsRuntimeMetadata) { // Dev12: If compiling to winmdobj, we need to add to PDB source spans of // all types and members for better error reporting by WinMDExp. nativePdbWriterOpt.WriteDefinitionLocations(mdWriter.Module.GetSymbolToLocationMap()); } else { #if DEBUG // validate that all definitions are writable // if same scenario would happen in an winmdobj project nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap()); #endif } } Stream peStream = getPeStream(); if (peStream == null) { return(false); } BlobContentId pdbContentId = nativePdbWriterOpt?.GetContentId() ?? default(BlobContentId); // the writer shall not be used after this point for writing: nativePdbWriterOpt = null; ushort portablePdbVersion = 0; var metadataSerializer = mdWriter.GetTypeSystemMetadataSerializer(); var peHeaderBuilder = new PEHeaderBuilder( machine: properties.Machine, sectionAlignment: properties.SectionAlignment, fileAlignment: properties.FileAlignment, imageBase: properties.BaseAddress, majorLinkerVersion: properties.LinkerMajorVersion, minorLinkerVersion: properties.LinkerMinorVersion, majorOperatingSystemVersion: 4, minorOperatingSystemVersion: 0, majorImageVersion: 0, minorImageVersion: 0, majorSubsystemVersion: properties.MajorSubsystemVersion, minorSubsystemVersion: properties.MinorSubsystemVersion, subsystem: properties.Subsystem, dllCharacteristics: properties.DllCharacteristics, imageCharacteristics: properties.ImageCharacteristics, sizeOfStackReserve: properties.SizeOfStackReserve, sizeOfStackCommit: properties.SizeOfStackCommit, sizeOfHeapReserve: properties.SizeOfHeapReserve, sizeOfHeapCommit: properties.SizeOfHeapCommit); var deterministicIdProvider = isDeterministic ? new Func <IEnumerable <Blob>, BlobContentId>(content => BlobContentId.FromHash(CryptographicHashProvider.ComputeSha1(content))) : null; if (mdWriter.EmitStandaloneDebugMetadata) { Debug.Assert(getPortablePdbStreamOpt != null); var debugMetadataBuilder = new BlobBuilder(); var debugMetadataSerializer = mdWriter.GetStandaloneDebugMetadataSerializer(metadataSerializer.MetadataSizes, debugEntryPointHandle, deterministicIdProvider); debugMetadataSerializer.SerializeMetadata(debugMetadataBuilder, out pdbContentId); portablePdbVersion = debugMetadataSerializer.FormatVersion; // write to Portable PDB stream: Stream portablePdbStream = getPortablePdbStreamOpt(); if (portablePdbStream != null) { debugMetadataBuilder.WriteContentTo(portablePdbStream); } } DebugDirectoryBuilder debugDirectoryBuilder; if (pdbPathOpt != null || isDeterministic) { debugDirectoryBuilder = new DebugDirectoryBuilder(); if (pdbPathOpt != null) { string paddedPath = isDeterministic ? pdbPathOpt : PadPdbPath(pdbPathOpt); debugDirectoryBuilder.AddCodeViewEntry(paddedPath, pdbContentId, portablePdbVersion); } if (isDeterministic) { debugDirectoryBuilder.AddReproducibleEntry(); } } else { debugDirectoryBuilder = null; } var peBuilder = new ManagedPEBuilder( peHeaderBuilder, metadataSerializer, ilBuilder, mappedFieldDataBuilder, managedResourceBuilder, CreateNativeResourceSectionSerializer(context.Module), debugDirectoryBuilder, CalculateStrongNameSignatureSize(context.Module), entryPointHandle, properties.CorFlags, deterministicIdProvider); var peBlob = new BlobBuilder(); BlobContentId peContentId; peBuilder.Serialize(peBlob, out peContentId); // Patch MVID if (!mvidFixup.IsDefault) { var writer = new BlobWriter(mvidFixup); writer.WriteGuid(peContentId.Guid); Debug.Assert(writer.RemainingBytes == 0); } try { peBlob.WriteContentTo(peStream); } catch (Exception e) when(!(e is OperationCanceledException)) { throw new PeWritingException(e); } return(true); }
public void EmitPortableExecutable() { bool succeeded = false; try { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); PEHeaderBuilder headerBuilder; int? timeDateStamp; ISymbolNode r2rHeaderExportSymbol; Func <IEnumerable <Blob>, BlobContentId> peIdProvider = null; if (_nodeFactory.CompilationModuleGroup.IsCompositeBuildMode && _componentModule == null) { headerBuilder = PEHeaderProvider.Create( imageCharacteristics: Characteristics.ExecutableImage | Characteristics.Dll, dllCharacteristics: default(DllCharacteristics), Subsystem.Unknown, _nodeFactory.Target); peIdProvider = new Func <IEnumerable <Blob>, BlobContentId>(content => BlobContentId.FromHash(CryptographicHashProvider.ComputeSourceHash(content))); timeDateStamp = null; r2rHeaderExportSymbol = _nodeFactory.Header; } else { PEReader inputPeReader = (_componentModule != null ? _componentModule.PEReader : _nodeFactory.CompilationModuleGroup.CompilationModuleSet.First().PEReader); headerBuilder = PEHeaderProvider.Copy(inputPeReader.PEHeaders, _nodeFactory.Target); timeDateStamp = inputPeReader.PEHeaders.CoffHeader.TimeDateStamp; r2rHeaderExportSymbol = null; } Func <RuntimeFunctionsTableNode> getRuntimeFunctionsTable = null; if (_componentModule == null) { getRuntimeFunctionsTable = GetRuntimeFunctionsTable; } R2RPEBuilder r2rPeBuilder = new R2RPEBuilder( _nodeFactory.Target, headerBuilder, r2rHeaderExportSymbol, Path.GetFileName(_objectFilePath), getRuntimeFunctionsTable, _customPESectionAlignment, peIdProvider); NativeDebugDirectoryEntryNode nativeDebugDirectoryEntryNode = null; ISymbolDefinitionNode firstImportThunk = null; ISymbolDefinitionNode lastImportThunk = null; ObjectNode lastWrittenObjectNode = null; int nodeIndex = -1; foreach (var depNode in _nodes) { ++nodeIndex; ObjectNode node = depNode as ObjectNode; if (node == null) { continue; } if (node.ShouldSkipEmittingObjectNode(_nodeFactory)) { continue; } ObjectData nodeContents = node.GetData(_nodeFactory); if (node is NativeDebugDirectoryEntryNode nddeNode) { // There should be only one NativeDebugDirectoryEntry. Debug.Assert(nativeDebugDirectoryEntryNode == null); nativeDebugDirectoryEntryNode = nddeNode; } if (node is ImportThunk importThunkNode) { Debug.Assert(firstImportThunk == null || lastWrittenObjectNode is ImportThunk, "All the import thunks must be in single contiguous run"); if (firstImportThunk == null) { firstImportThunk = importThunkNode; } lastImportThunk = importThunkNode; } string name = null; if (_mapFileBuilder != null) { name = depNode.GetType().ToString(); int firstGeneric = name.IndexOf('['); if (firstGeneric < 0) { firstGeneric = name.Length; } int lastDot = name.LastIndexOf('.', firstGeneric - 1, firstGeneric); if (lastDot > 0) { name = name.Substring(lastDot + 1); } } EmitObjectData(r2rPeBuilder, nodeContents, nodeIndex, name, node.Section); lastWrittenObjectNode = node; if ((_generatePdbFile || _generatePerfMapFile) && node is MethodWithGCInfo methodNode) { _outputInfoBuilder.AddMethod(methodNode, nodeContents.DefinedSymbols[0]); } } r2rPeBuilder.SetCorHeader(_nodeFactory.CopiedCorHeaderNode, _nodeFactory.CopiedCorHeaderNode.Size); r2rPeBuilder.SetDebugDirectory(_nodeFactory.DebugDirectoryNode, _nodeFactory.DebugDirectoryNode.Size); if (firstImportThunk != null) { r2rPeBuilder.AddSymbolForRange(_nodeFactory.DelayLoadMethodCallThunks, firstImportThunk, lastImportThunk); } if (_nodeFactory.Win32ResourcesNode != null) { Debug.Assert(_nodeFactory.Win32ResourcesNode.Size != 0); r2rPeBuilder.SetWin32Resources(_nodeFactory.Win32ResourcesNode, _nodeFactory.Win32ResourcesNode.Size); } using (var peStream = File.Create(_objectFilePath)) { r2rPeBuilder.Write(peStream, timeDateStamp); if (_mapFileBuilder != null) { _mapFileBuilder.SetFileSize(peStream.Length); } // Compute MD5 hash of the output image and store that in the native DebugDirectory entry using (var md5Hash = MD5.Create()) { peStream.Seek(0, SeekOrigin.Begin); byte[] hash = md5Hash.ComputeHash(peStream); byte[] rsdsEntry = nativeDebugDirectoryEntryNode.GenerateRSDSEntryData(hash); int offsetToUpdate = r2rPeBuilder.GetSymbolFilePosition(nativeDebugDirectoryEntryNode); peStream.Seek(offsetToUpdate, SeekOrigin.Begin); peStream.Write(rsdsEntry); } } if (_outputInfoBuilder != null) { r2rPeBuilder.AddSections(_outputInfoBuilder); if (_generateMapFile) { string mapFileName = Path.ChangeExtension(_objectFilePath, ".map"); _mapFileBuilder.SaveMap(mapFileName); } if (_generateMapCsvFile) { string nodeStatsCsvFileName = Path.ChangeExtension(_objectFilePath, ".nodestats.csv"); string mapCsvFileName = Path.ChangeExtension(_objectFilePath, ".map.csv"); _mapFileBuilder.SaveCsv(nodeStatsCsvFileName, mapCsvFileName); } if (_generatePdbFile) { string path = _pdbPath; if (string.IsNullOrEmpty(path)) { path = Path.GetDirectoryName(_objectFilePath); } _symbolFileBuilder.SavePdb(path, _objectFilePath); } if (_generatePerfMapFile) { string path = _perfMapPath; if (string.IsNullOrEmpty(path)) { path = Path.GetDirectoryName(_objectFilePath); } _symbolFileBuilder.SavePerfMap(path, _objectFilePath); } if (_profileFileBuilder != null) { string path = Path.ChangeExtension(_objectFilePath, ".profile"); _profileFileBuilder.SaveProfile(path); } } succeeded = true; } finally { if (!succeeded) { // If there was an exception while generating the OBJ file, make sure we don't leave the unfinished // object file around. try { File.Delete(_objectFilePath); } catch { } } } }
internal ImmutableArray <byte> GetSha1Checksum() { if (this.lazySha1Checksum.IsDefault) { // we shouldn't be asking for a checksum of encoding-less source text: Debug.Assert(this.Encoding != null); var stream = new MemoryStream(); using (var writer = new StreamWriter(stream, this.Encoding)) { this.Write(writer); writer.Flush(); stream.Seek(0, SeekOrigin.Begin); ImmutableInterlocked.InterlockedCompareExchange(ref lazySha1Checksum, CryptographicHashProvider.ComputeSha1(stream), default(ImmutableArray <byte>)); } } return(this.lazySha1Checksum); }