< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 141
Coverable lines: 141
Total lines: 243
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 46
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)0%10100%
CreateDefaultDebugDirectoryBuilder()0%220%
CreateSections()0%660%
SerializeSection(...)0%440%
SerializeTextSection(...)0%10100%
SerializeResourceSection(...)100%110%
SerializeRelocationSection(...)100%110%
WriteRelocationSection(...)0%10100%
GetDirectories()100%110%
Sign(...)0%440%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedPEBuilder.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Collections.Generic;
 5using System.Collections.Immutable;
 6using System.Diagnostics;
 7using System.Reflection.Metadata;
 8using System.Reflection.Metadata.Ecma335;
 9
 10namespace System.Reflection.PortableExecutable
 11{
 12    public class ManagedPEBuilder : PEBuilder
 13    {
 14        public const int ManagedResourcesDataAlignment = ManagedTextSection.ManagedResourcesDataAlignment;
 15        public const int MappedFieldDataAlignment = ManagedTextSection.MappedFieldDataAlignment;
 16
 17        private const int DefaultStrongNameSignatureSize = 128;
 18
 19        private const string TextSectionName = ".text";
 20        private const string ResourceSectionName = ".rsrc";
 21        private const string RelocationSectionName = ".reloc";
 22
 23        private readonly PEDirectoriesBuilder _peDirectoriesBuilder;
 24        private readonly MetadataRootBuilder _metadataRootBuilder;
 25        private readonly BlobBuilder _ilStream;
 26        private readonly BlobBuilder? _mappedFieldDataOpt;
 27        private readonly BlobBuilder? _managedResourcesOpt;
 28        private readonly ResourceSectionBuilder? _nativeResourcesOpt;
 29        private readonly int _strongNameSignatureSize;
 30        private readonly MethodDefinitionHandle _entryPointOpt;
 31        private readonly DebugDirectoryBuilder? _debugDirectoryBuilderOpt;
 32        private readonly CorFlags _corFlags;
 33
 34        private int _lazyEntryPointAddress;
 35        private Blob _lazyStrongNameSignature;
 36
 37        public ManagedPEBuilder(
 38            PEHeaderBuilder header,
 39            MetadataRootBuilder metadataRootBuilder,
 40            BlobBuilder ilStream,
 41            BlobBuilder? mappedFieldData = null,
 42            BlobBuilder? managedResources = null,
 43            ResourceSectionBuilder? nativeResources = null,
 44            DebugDirectoryBuilder? debugDirectoryBuilder = null,
 45            int strongNameSignatureSize = DefaultStrongNameSignatureSize,
 46            MethodDefinitionHandle entryPoint = default(MethodDefinitionHandle),
 47            CorFlags flags = CorFlags.ILOnly,
 48            Func<IEnumerable<Blob>, BlobContentId>? deterministicIdProvider = null)
 049            : base(header, deterministicIdProvider)
 050        {
 051            if (header is null)
 052            {
 053                Throw.ArgumentNull(nameof(header));
 54            }
 055            if (metadataRootBuilder is null)
 056            {
 057                Throw.ArgumentNull(nameof(metadataRootBuilder));
 58            }
 059            if (ilStream is null)
 060            {
 061                Throw.ArgumentNull(nameof(ilStream));
 62            }
 63
 064            if (strongNameSignatureSize < 0)
 065            {
 066                Throw.ArgumentOutOfRange(nameof(strongNameSignatureSize));
 67            }
 68
 069            _metadataRootBuilder = metadataRootBuilder;
 070            _ilStream = ilStream;
 071            _mappedFieldDataOpt = mappedFieldData;
 072            _managedResourcesOpt = managedResources;
 073            _nativeResourcesOpt = nativeResources;
 074            _strongNameSignatureSize = strongNameSignatureSize;
 075            _entryPointOpt = entryPoint;
 076            _debugDirectoryBuilderOpt = debugDirectoryBuilder ?? CreateDefaultDebugDirectoryBuilder();
 077            _corFlags = flags;
 78
 079            _peDirectoriesBuilder = new PEDirectoriesBuilder();
 080        }
 81
 82        private DebugDirectoryBuilder? CreateDefaultDebugDirectoryBuilder()
 083        {
 084            if (IsDeterministic)
 085            {
 086                var builder = new DebugDirectoryBuilder();
 087                builder.AddReproducibleEntry();
 088                return builder;
 89            }
 90
 091            return null;
 092        }
 93
 94        protected override ImmutableArray<Section> CreateSections()
 095        {
 096            var builder = ImmutableArray.CreateBuilder<Section>(3);
 097            builder.Add(new Section(TextSectionName, SectionCharacteristics.MemRead | SectionCharacteristics.MemExecute 
 98
 099            if (_nativeResourcesOpt != null)
 0100            {
 0101                builder.Add(new Section(ResourceSectionName, SectionCharacteristics.MemRead | SectionCharacteristics.Con
 0102            }
 103
 0104            if (Header.Machine == Machine.I386 || Header.Machine == 0)
 0105            {
 0106                builder.Add(new Section(RelocationSectionName, SectionCharacteristics.MemRead | SectionCharacteristics.M
 0107            }
 108
 0109            return builder.ToImmutable();
 0110        }
 111
 112        protected override BlobBuilder SerializeSection(string name, SectionLocation location) =>
 0113            name switch
 0114            {
 0115                TextSectionName => SerializeTextSection(location),
 0116                ResourceSectionName => SerializeResourceSection(location),
 0117                RelocationSectionName => SerializeRelocationSection(location),
 0118                _ => throw new ArgumentException(SR.Format(SR.UnknownSectionName, name), nameof(name)),
 0119            };
 120
 121        private BlobBuilder SerializeTextSection(SectionLocation location)
 0122        {
 0123            var sectionBuilder = new BlobBuilder();
 0124            var metadataBuilder = new BlobBuilder();
 125
 0126            var metadataSizes = _metadataRootBuilder.Sizes;
 127
 0128            var textSection = new ManagedTextSection(
 0129                imageCharacteristics: Header.ImageCharacteristics,
 0130                machine: Header.Machine,
 0131                ilStreamSize: _ilStream.Count,
 0132                metadataSize: metadataSizes.MetadataSize,
 0133                resourceDataSize: _managedResourcesOpt?.Count ?? 0,
 0134                strongNameSignatureSize: _strongNameSignatureSize,
 0135                debugDataSize: _debugDirectoryBuilderOpt?.Size ?? 0,
 0136                mappedFieldDataSize: _mappedFieldDataOpt?.Count ?? 0);
 137
 0138            int methodBodyStreamRva = location.RelativeVirtualAddress + textSection.OffsetToILStream;
 0139            int mappedFieldDataStreamRva = location.RelativeVirtualAddress + textSection.CalculateOffsetToMappedFieldDat
 0140            _metadataRootBuilder.Serialize(metadataBuilder, methodBodyStreamRva, mappedFieldDataStreamRva);
 141
 142            DirectoryEntry debugDirectoryEntry;
 143            BlobBuilder? debugTableBuilderOpt;
 0144            if (_debugDirectoryBuilderOpt != null)
 0145            {
 0146                int debugDirectoryOffset = textSection.ComputeOffsetToDebugDirectory();
 0147                debugTableBuilderOpt = new BlobBuilder(_debugDirectoryBuilderOpt.TableSize);
 0148                _debugDirectoryBuilderOpt.Serialize(debugTableBuilderOpt, location, debugDirectoryOffset);
 149
 150                // Only the size of the fixed part of the debug table goes here.
 0151                debugDirectoryEntry = new DirectoryEntry(
 0152                    location.RelativeVirtualAddress + debugDirectoryOffset,
 0153                    _debugDirectoryBuilderOpt.TableSize);
 0154            }
 155            else
 0156            {
 0157                debugTableBuilderOpt = null;
 0158                debugDirectoryEntry = default(DirectoryEntry);
 0159            }
 160
 0161            _lazyEntryPointAddress = textSection.GetEntryPointAddress(location.RelativeVirtualAddress);
 162
 0163            textSection.Serialize(
 0164                sectionBuilder,
 0165                location.RelativeVirtualAddress,
 0166                _entryPointOpt.IsNil ? 0 : MetadataTokens.GetToken(_entryPointOpt),
 0167                _corFlags,
 0168                Header.ImageBase,
 0169                metadataBuilder,
 0170                _ilStream,
 0171                _mappedFieldDataOpt,
 0172                _managedResourcesOpt,
 0173                debugTableBuilderOpt,
 0174                out _lazyStrongNameSignature);
 175
 0176            _peDirectoriesBuilder.AddressOfEntryPoint = _lazyEntryPointAddress;
 0177            _peDirectoriesBuilder.DebugTable = debugDirectoryEntry;
 0178            _peDirectoriesBuilder.ImportAddressTable = textSection.GetImportAddressTableDirectoryEntry(location.Relative
 0179            _peDirectoriesBuilder.ImportTable = textSection.GetImportTableDirectoryEntry(location.RelativeVirtualAddress
 0180            _peDirectoriesBuilder.CorHeaderTable = textSection.GetCorHeaderDirectoryEntry(location.RelativeVirtualAddres
 181
 0182            return sectionBuilder;
 0183        }
 184
 185        private BlobBuilder SerializeResourceSection(SectionLocation location)
 0186        {
 0187            Debug.Assert(_nativeResourcesOpt != null);
 188
 0189            var sectionBuilder = new BlobBuilder();
 0190            _nativeResourcesOpt.Serialize(sectionBuilder, location);
 191
 0192            _peDirectoriesBuilder.ResourceTable = new DirectoryEntry(location.RelativeVirtualAddress, sectionBuilder.Cou
 0193            return sectionBuilder;
 0194        }
 195
 196        private BlobBuilder SerializeRelocationSection(SectionLocation location)
 0197        {
 0198            var sectionBuilder = new BlobBuilder();
 0199            WriteRelocationSection(sectionBuilder, Header.Machine, _lazyEntryPointAddress);
 200
 0201            _peDirectoriesBuilder.BaseRelocationTable = new DirectoryEntry(location.RelativeVirtualAddress, sectionBuild
 0202            return sectionBuilder;
 0203        }
 204
 205        private static void WriteRelocationSection(BlobBuilder builder, Machine machine, int entryPointAddress)
 0206        {
 0207            Debug.Assert(builder.Count == 0);
 208
 0209            builder.WriteUInt32((((uint)entryPointAddress + 2) / 0x1000) * 0x1000);
 0210            builder.WriteUInt32((machine == Machine.IA64) ? 14u : 12u);
 0211            uint offsetWithinPage = ((uint)entryPointAddress + 2) % 0x1000;
 0212            uint relocType = (machine == Machine.Amd64 || machine == Machine.IA64 || machine == Machine.Arm64) ? 10u : 3
 0213            ushort s = (ushort)((relocType << 12) | offsetWithinPage);
 0214            builder.WriteUInt16(s);
 0215            if (machine == Machine.IA64)
 0216            {
 0217                builder.WriteUInt32(relocType << 12);
 0218            }
 219
 0220            builder.WriteUInt16(0); // next chunk's RVA
 0221        }
 222
 223        protected internal override PEDirectoriesBuilder GetDirectories()
 0224        {
 0225            return _peDirectoriesBuilder;
 0226        }
 227
 228        public void Sign(BlobBuilder peImage, Func<IEnumerable<Blob>, byte[]> signatureProvider)
 0229        {
 0230            if (peImage is null)
 0231            {
 0232                Throw.ArgumentNull(nameof(peImage));
 233            }
 0234            if (signatureProvider is null)
 0235            {
 0236                Throw.ArgumentNull(nameof(signatureProvider));
 237            }
 238
 0239            Sign(peImage!, _lazyStrongNameSignature, signatureProvider!);
 0240        }
 241    }
 242}
 243