/// <summary> /// Constructor initializes the various control structures and combines the section list. /// </summary> /// <param name="target">Target environment specifier</param> /// <param name="peReader">Input MSIL PE file reader</param> /// <param name="sectionStartNodeLookup">Callback to locate section start node for a given section name</param> /// <param name="getRuntimeFunctionsTable">Callback to retrieve the runtime functions table</param> public R2RPEBuilder( TargetDetails target, PEReader peReader, Func <string, ISymbolNode> sectionStartNodeLookup, Func <RuntimeFunctionsTableNode> getRuntimeFunctionsTable) : base(PEHeaderCopier.Copy(peReader.PEHeaders, target), deterministicIdProvider: null) { _target = target; _peReader = peReader; _getRuntimeFunctionsTable = getRuntimeFunctionsTable; _sectionRvaDeltas = new List <SectionRVADelta>(); _sectionBuilder = new SectionBuilder(target); _sectionBuilder.SetSectionStartNodeLookup(sectionStartNodeLookup); _textSectionIndex = _sectionBuilder.AddSection(R2RPEBuilder.TextSectionName, SectionCharacteristics.ContainsCode | SectionCharacteristics.MemExecute | SectionCharacteristics.MemRead, 512); _rdataSectionIndex = _sectionBuilder.AddSection(".rdata", SectionCharacteristics.ContainsInitializedData | SectionCharacteristics.MemRead, 512); _dataSectionIndex = _sectionBuilder.AddSection(".data", SectionCharacteristics.ContainsInitializedData | SectionCharacteristics.MemWrite | SectionCharacteristics.MemRead, 512); _customSections = new HashSet <string>(); foreach (SectionInfo section in _sectionBuilder.GetSections()) { _customSections.Add(section.SectionName); } foreach (SectionHeader sectionHeader in peReader.PEHeaders.SectionHeaders) { if (_sectionBuilder.FindSection(sectionHeader.Name) == null) { _sectionBuilder.AddSection(sectionHeader.Name, sectionHeader.SectionCharacteristics, peReader.PEHeaders.PEHeader.SectionAlignment); } } if (_sectionBuilder.FindSection(R2RPEBuilder.RelocSectionName) == null) { // Always inject the relocation section to the end of section list _sectionBuilder.AddSection( R2RPEBuilder.RelocSectionName, SectionCharacteristics.ContainsInitializedData | SectionCharacteristics.MemRead | SectionCharacteristics.MemDiscardable, peReader.PEHeaders.PEHeader.SectionAlignment); } ImmutableArray <Section> .Builder sectionListBuilder = ImmutableArray.CreateBuilder <Section>(); foreach (SectionInfo sectionInfo in _sectionBuilder.GetSections()) { ILCompiler.PEWriter.Section builderSection = _sectionBuilder.FindSection(sectionInfo.SectionName); Debug.Assert(builderSection != null); sectionListBuilder.Add(new Section(builderSection.Name, builderSection.Characteristics)); } _sections = sectionListBuilder.ToImmutableArray(); _sectionRVAs = new int[_sections.Length]; _sectionRawSizes = new int[_sections.Length]; }
/// <summary> /// Constructor initializes the various control structures and combines the section list. /// </summary> /// <param name="target">Target environment specifier</param> /// <param name="peHeaderBuilder">PE file header builder</param> /// <param name="getRuntimeFunctionsTable">Callback to retrieve the runtime functions table</param> public R2RPEBuilder( TargetDetails target, PEHeaderBuilder peHeaderBuilder, ISymbolNode r2rHeaderExportSymbol, string outputFileSimpleName, Func <RuntimeFunctionsTableNode> getRuntimeFunctionsTable, int customPESectionAlignment, Func <IEnumerable <Blob>, BlobContentId> deterministicIdProvider) : base(peHeaderBuilder, deterministicIdProvider: deterministicIdProvider) { _target = target; _getRuntimeFunctionsTable = getRuntimeFunctionsTable; _sectionRvaDeltas = new List <SectionRVADelta>(); _sectionBuilder = new SectionBuilder(target); _textSectionIndex = _sectionBuilder.AddSection(TextSectionName, SectionCharacteristics.ContainsCode | SectionCharacteristics.MemExecute | SectionCharacteristics.MemRead, 512); _dataSectionIndex = _sectionBuilder.AddSection(DataSectionName, SectionCharacteristics.ContainsInitializedData | SectionCharacteristics.MemWrite | SectionCharacteristics.MemRead, 512); _customPESectionAlignment = customPESectionAlignment; if (r2rHeaderExportSymbol != null) { _sectionBuilder.AddSection(R2RPEBuilder.ExportDataSectionName, SectionCharacteristics.ContainsInitializedData | SectionCharacteristics.MemRead, 512); _sectionBuilder.AddExportSymbol("RTR_HEADER", 1, r2rHeaderExportSymbol); _sectionBuilder.SetDllNameForExportDirectoryTable(outputFileSimpleName); } if (_sectionBuilder.FindSection(R2RPEBuilder.RelocSectionName) == null) { // Always inject the relocation section to the end of section list _sectionBuilder.AddSection( R2RPEBuilder.RelocSectionName, SectionCharacteristics.ContainsInitializedData | SectionCharacteristics.MemRead | SectionCharacteristics.MemDiscardable, PEHeaderConstants.SectionAlignment); } ImmutableArray <Section> .Builder sectionListBuilder = ImmutableArray.CreateBuilder <Section>(); foreach (SectionInfo sectionInfo in _sectionBuilder.GetSections()) { ILCompiler.PEWriter.Section builderSection = _sectionBuilder.FindSection(sectionInfo.SectionName); Debug.Assert(builderSection != null); sectionListBuilder.Add(new Section(builderSection.Name, builderSection.Characteristics)); } _sections = sectionListBuilder.ToImmutableArray(); _sectionRVAs = new int[_sections.Length]; _sectionPointerToRawData = new int[_sections.Length]; _sectionRawSizes = new int[_sections.Length]; }
/// <summary> /// Emit built sections using the R2R PE writer. /// </summary> /// <param name="builder">Section builder to emit</param> /// <param name="machine">Target machine architecture</param> /// <param name="inputReader">Input MSIL reader</param> /// <param name="outputStream">Output stream for the final R2R PE file</param> public static void EmitR2R( this SectionBuilder builder, Machine machine, PEReader inputReader, Action <PEDirectoriesBuilder> directoriesUpdater, Stream outputStream) { R2RPEBuilder r2rBuilder = new R2RPEBuilder( machine: machine, peReader: inputReader, sectionNames: builder.GetSections(), sectionSerializer: builder.SerializeSection, directoriesUpdater: (PEDirectoriesBuilder directoriesBuilder) => { builder.UpdateDirectories(directoriesBuilder); if (directoriesUpdater != null) { directoriesUpdater(directoriesBuilder); } }); BlobBuilder outputPeFile = new BlobBuilder(); r2rBuilder.Serialize(outputPeFile); CorHeaderBuilder corHeader = r2rBuilder.CorHeader; if (corHeader != null) { corHeader.Flags = (r2rBuilder.CorHeader.Flags & ~CorFlags.ILOnly) | CorFlags.ILLibrary; corHeader.MetadataDirectory = r2rBuilder.RelocateDirectoryEntry(corHeader.MetadataDirectory); corHeader.ResourcesDirectory = r2rBuilder.RelocateDirectoryEntry(corHeader.ResourcesDirectory); corHeader.StrongNameSignatureDirectory = r2rBuilder.RelocateDirectoryEntry(corHeader.StrongNameSignatureDirectory); corHeader.CodeManagerTableDirectory = r2rBuilder.RelocateDirectoryEntry(corHeader.CodeManagerTableDirectory); corHeader.VtableFixupsDirectory = r2rBuilder.RelocateDirectoryEntry(corHeader.VtableFixupsDirectory); corHeader.ExportAddressTableJumpsDirectory = r2rBuilder.RelocateDirectoryEntry(corHeader.ExportAddressTableJumpsDirectory); corHeader.ManagedNativeHeaderDirectory = r2rBuilder.RelocateDirectoryEntry(corHeader.ManagedNativeHeaderDirectory); builder.UpdateCorHeader(corHeader); } builder.RelocateOutputFile( outputPeFile, inputReader.PEHeaders.PEHeader.ImageBase, corHeader, r2rBuilder.CorHeaderFileOffset, outputStream); r2rBuilder.RelocateMetadataBlob(outputStream); }