<commit_before>﻿using AsmResolver.Emit;
using AsmResolver.Net.Metadata;

namespace AsmResolver.Net.Emit
{
    public class CompactNetTextContents : FileSegmentBuilder
    {
        private readonly SimpleFileSegmentBuilder _importDirectory = new SimpleFileSegmentBuilder();
        
        public CompactNetTextContents(WindowsAssembly assembly)
        {
            ImportBuffer = new ImportDirectoryBuffer(assembly);
            
            Segments.Add(ImportBuffer.AddressTables);
            Segments.Add(NetDirectory = assembly.NetDirectory);
            Segments.Add(MethodBodyTable = new MethodBodyTableBuffer());

            if (assembly.NetDirectory.ResourcesManifest != null)
                Segments.Add(assembly.NetDirectory.ResourcesManifest);

            Segments.Add(FieldDataTable = new SimpleFileSegmentBuilder());
            Segments.Add(MetadataDirectory = new MetadataDirectoryBuffer(assembly.NetDirectory.MetadataHeader));

            if (assembly.DebugDirectory != null)
            {
                Segments.Add(DebugDirectory = assembly.DebugDirectory);
                Segments.Add(assembly.DebugDirectory.Data);
            }

            if (NetDirectory.StrongNameData != null)
                Segments.Add(NetDirectory.StrongNameData);

            if (NetDirectory.VTablesDirectory != null)
            {
                VTableFixups = new VTableFixupsBuffer(NetDirectory.VTablesDirectory);
                Segments.Add(VTableFixups.Directory);
                Segments.Add(VTableFixups.EntriesTable);
            }

            if (assembly.ExportDirectory != null)
            {
                Segments.Add(ExportDirectory = new ExportDirectoryBuffer(assembly.ExportDirectory, assembly));
            }

            _importDirectory.Segments.Add(ImportBuffer.ModuleImportTable);
            _importDirectory.Segments.Add(ImportBuffer.LookupTables);
            _importDirectory.Segments.Add(ImportBuffer.NameTable);
            Segments.Add(_importDirectory);

            Segments.Add(Bootstrapper = new BootstrapperSegment());

            foreach (var method in assembly.NetDirectory.MetadataHeader.GetStream<TableStream>()
                .GetTable<MethodDefinitionTable>())
            {
                if (method.Column1 != null)
                    MethodBodyTable.Segments.Add(method.Column1);
            }

        }

        public ImportDirectoryBuffer ImportBuffer
        {
            get;
        }

        public FileSegment ImportDirectory => _importDirectory;

        public ExportDirectoryBuffer ExportDirectory
        {
            get;
        }

        public ImageNetDirectory NetDirectory
        {
            get;
        }

        public MethodBodyTableBuffer MethodBodyTable
        {
            get;
        }

        public SimpleFileSegmentBuilder FieldDataTable
        {
            get;
        }

        public MetadataDirectoryBuffer MetadataDirectory
        {
            get;
        }

        public ImageDebugDirectory DebugDirectory
        {
            get;
        }

        public VTableFixupsBuffer VTableFixups
        {
            get;
        }

        public BootstrapperSegment Bootstrapper
        {
            get;
        }

        public override void UpdateReferences(EmitContext context)
        {
            ImportBuffer.UpdateTableRvas();
            VTableFixups?.UpdateTableRvas(context);
            if (DebugDirectory != null)
            {
                DebugDirectory.PointerToRawData = (uint) DebugDirectory.Data.StartOffset;
                DebugDirectory.AddressOfRawData =
                    (uint) context.Builder.Assembly.FileOffsetToRva(DebugDirectory.PointerToRawData);
                DebugDirectory.SizeOfData = DebugDirectory.Data.GetPhysicalLength();
            }
           
            UpdateNetDirectory(context);
            base.UpdateReferences(context);
        }

        private void UpdateNetDirectory(EmitContext context)
        {
            var assembly = NetDirectory.Assembly;
            NetDirectory.MetadataDirectory.VirtualAddress = (uint) assembly.FileOffsetToRva(MetadataDirectory.StartOffset);
            NetDirectory.MetadataDirectory.Size = MetadataDirectory.GetPhysicalLength();

            if (NetDirectory.ResourcesManifest != null)
            {
                NetDirectory.ResourcesDirectory.VirtualAddress = (uint) assembly.FileOffsetToRva(NetDirectory.ResourcesManifest.StartOffset);
                NetDirectory.ResourcesDirectory.Size = NetDirectory.ResourcesManifest.GetPhysicalLength();
            }
            
            if (NetDirectory.StrongNameData != null)
            {
                NetDirectory.StrongNameSignatureDirectory.VirtualAddress =
                    (uint) assembly.FileOffsetToRva(NetDirectory.StrongNameData.StartOffset);
                NetDirectory.StrongNameSignatureDirectory.Size = NetDirectory.StrongNameData.GetPhysicalLength();
            }
            
            if (VTableFixups != null)
            {
                NetDirectory.VTableFixupsDirectory.VirtualAddress =
                    (uint) assembly.FileOffsetToRva(VTableFixups.Directory.StartOffset);
                NetDirectory.VTableFixupsDirectory.Size = VTableFixups.Directory.GetPhysicalLength();
            }
        }

    }
}
<commit_msg>Field data now emitted to final assembly.<commit_after>﻿using AsmResolver.Emit;
using AsmResolver.Net.Metadata;

namespace AsmResolver.Net.Emit
{
    /// <summary>
    /// Represents a structure of the .text section of a typical .NET assembly.  
    /// </summary>
    public class CompactNetTextContents : FileSegmentBuilder
    {
        private readonly SimpleFileSegmentBuilder _importDirectory = new SimpleFileSegmentBuilder();
        
        public CompactNetTextContents(WindowsAssembly assembly)
        {
            ImportBuffer = new ImportDirectoryBuffer(assembly);
            
            // IAT
            Segments.Add(ImportBuffer.AddressTables);
            
            // .NET Directory
            Segments.Add(NetDirectory = assembly.NetDirectory);
            
            // Method bodies.
            Segments.Add(MethodBodyTable = new MethodBodyTableBuffer());

            // Manifest resource data.
            if (assembly.NetDirectory.ResourcesManifest != null)
                Segments.Add(assembly.NetDirectory.ResourcesManifest);

            // Field data (FieldRVAs).
            Segments.Add(FieldDataTable = new SimpleFileSegmentBuilder());
            
            // Metadata directory header.
            Segments.Add(MetadataDirectory = new MetadataDirectoryBuffer(assembly.NetDirectory.MetadataHeader));

            // Debug directory.
            if (assembly.DebugDirectory != null)
            {
                Segments.Add(DebugDirectory = assembly.DebugDirectory);
                Segments.Add(assembly.DebugDirectory.Data);
            }

            // Strong name.
            if (NetDirectory.StrongNameData != null)
                Segments.Add(NetDirectory.StrongNameData);

            // VTables.
            if (NetDirectory.VTablesDirectory != null)
            {
                VTableFixups = new VTableFixupsBuffer(NetDirectory.VTablesDirectory);
                Segments.Add(VTableFixups.Directory);
                Segments.Add(VTableFixups.EntriesTable);
            }

            // Export directory.
            if (assembly.ExportDirectory != null)
                Segments.Add(ExportDirectory = new ExportDirectoryBuffer(assembly.ExportDirectory, assembly));

            // Remaining bits of the import tables.
            _importDirectory.Segments.Add(ImportBuffer.ModuleImportTable);
            _importDirectory.Segments.Add(ImportBuffer.LookupTables);
            _importDirectory.Segments.Add(ImportBuffer.NameTable);
            Segments.Add(_importDirectory);

            // Bootstrapper (Call to _CorExeMain / _CorDllMain).
            Segments.Add(Bootstrapper = new BootstrapperSegment());

            var tableStream = assembly.NetDirectory.MetadataHeader.GetStream<TableStream>();
            
            // Initialize field data segment.
            foreach (var fieldRva in tableStream.GetTable<FieldRvaTable>())
            {
                if (fieldRva.Column1 != null)
                    FieldDataTable.Segments.Add(fieldRva.Column1);
            }
            
            // Initialize method body table.
            foreach (var method in tableStream.GetTable<MethodDefinitionTable>())
            {
                if (method.Column1 != null)
                    MethodBodyTable.Segments.Add(method.Column1);
            }

        }

        public ImportDirectoryBuffer ImportBuffer
        {
            get;
        }

        public FileSegment ImportDirectory => _importDirectory;

        public ExportDirectoryBuffer ExportDirectory
        {
            get;
        }

        public ImageNetDirectory NetDirectory
        {
            get;
        }

        public MethodBodyTableBuffer MethodBodyTable
        {
            get;
        }

        public SimpleFileSegmentBuilder FieldDataTable
        {
            get;
        }

        public MetadataDirectoryBuffer MetadataDirectory
        {
            get;
        }

        public ImageDebugDirectory DebugDirectory
        {
            get;
        }

        public VTableFixupsBuffer VTableFixups
        {
            get;
        }

        public BootstrapperSegment Bootstrapper
        {
            get;
        }

        public override void UpdateReferences(EmitContext context)
        {
            ImportBuffer.UpdateTableRvas();
            VTableFixups?.UpdateTableRvas(context);
            if (DebugDirectory != null)
            {
                DebugDirectory.PointerToRawData = (uint) DebugDirectory.Data.StartOffset;
                DebugDirectory.AddressOfRawData =
                    (uint) context.Builder.Assembly.FileOffsetToRva(DebugDirectory.PointerToRawData);
                DebugDirectory.SizeOfData = DebugDirectory.Data.GetPhysicalLength();
            }
           
            UpdateNetDirectory(context);
            base.UpdateReferences(context);
        }

        private void UpdateNetDirectory(EmitContext context)
        {
            var assembly = NetDirectory.Assembly;
            NetDirectory.MetadataDirectory.VirtualAddress = (uint) assembly.FileOffsetToRva(MetadataDirectory.StartOffset);
            NetDirectory.MetadataDirectory.Size = MetadataDirectory.GetPhysicalLength();

            if (NetDirectory.ResourcesManifest != null)
            {
                NetDirectory.ResourcesDirectory.VirtualAddress = (uint) assembly.FileOffsetToRva(NetDirectory.ResourcesManifest.StartOffset);
                NetDirectory.ResourcesDirectory.Size = NetDirectory.ResourcesManifest.GetPhysicalLength();
            }
            
            if (NetDirectory.StrongNameData != null)
            {
                NetDirectory.StrongNameSignatureDirectory.VirtualAddress =
                    (uint) assembly.FileOffsetToRva(NetDirectory.StrongNameData.StartOffset);
                NetDirectory.StrongNameSignatureDirectory.Size = NetDirectory.StrongNameData.GetPhysicalLength();
            }
            
            if (VTableFixups != null)
            {
                NetDirectory.VTableFixupsDirectory.VirtualAddress =
                    (uint) assembly.FileOffsetToRva(VTableFixups.Directory.StartOffset);
                NetDirectory.VTableFixupsDirectory.Size = VTableFixups.Directory.GetPhysicalLength();
            }
        }
    }
}

{'fraction_non_alphanumeric': 0.0725611857980007, 'fraction_numerical': 0.000517063081695967, 'mean_word_length': 1.8961816820564013, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6193345', 'n_tokens_mistral': 2737, 'n_tokens_neox': 2623, 'n_words': 423}