├── .editorconfig
├── .github
└── workflows
│ └── build.yml
├── .gitignore
├── Examples
├── Example1.cs
├── Example2.cs
├── Example3.cs
├── Example4.cs
├── Example5.cs
├── Example6.cs
├── Example7.cs
├── Examples.csproj
└── Program.cs
├── LICENSE.txt
├── README.md
├── build.ps1
├── dnlib.sln
├── dnlib.snk
└── src
├── DefaultDllImportSearchPathsAttribute.cs
├── DotNet
├── AllTypesHelper.cs
├── AssemblyAttributes.cs
├── AssemblyDef.cs
├── AssemblyHash.cs
├── AssemblyHashAlgorithm.cs
├── AssemblyNameComparer.cs
├── AssemblyNameInfo.cs
├── AssemblyRef.cs
├── AssemblyResolver.cs
├── CallingConvention.cs
├── CallingConventionSig.cs
├── ClassLayout.cs
├── Constant.cs
├── CorLibTypes.cs
├── CpuArch.cs
├── CustomAttribute.cs
├── CustomAttributeCollection.cs
├── CustomAttributeReader.cs
├── DeclSecurity.cs
├── DeclSecurityReader.cs
├── ElementType.cs
├── Emit
│ ├── Code.cs
│ ├── DynamicMethodBodyReader.cs
│ ├── ExceptionHandler.cs
│ ├── ExceptionHandlerType.cs
│ ├── Extensions.cs
│ ├── FlowControl.cs
│ ├── Instruction.cs
│ ├── InstructionPrinter.cs
│ ├── InvalidMethodException.cs
│ ├── LocalList.cs
│ ├── MethodBody.cs
│ ├── MethodBodyReader.cs
│ ├── MethodBodyReaderBase.cs
│ ├── MethodTableToTypeConverter.cs
│ ├── MethodUtils.cs
│ ├── OpCode.cs
│ ├── OpCodeType.cs
│ ├── OpCodes.cs
│ ├── OperandType.cs
│ └── StackBehaviour.cs
├── EventAttributes.cs
├── EventDef.cs
├── ExportedType.cs
├── Extensions.cs
├── FieldAttributes.cs
├── FieldDef.cs
├── FileAttributes.cs
├── FileDef.cs
├── FrameworkRedirect.cs
├── FullNameFactory.cs
├── GenericArguments.cs
├── GenericParam.cs
├── GenericParamAttributes.cs
├── GenericParamConstraint.cs
├── GenericParamContext.cs
├── IAssemblyResolver.cs
├── ICodedToken.cs
├── ICorLibTypes.cs
├── ICustomAttribute.cs
├── IDecrypters.cs
├── ILogger.cs
├── IResolver.cs
├── ITokenResolver.cs
├── IType.cs
├── ITypeDefFinder.cs
├── IVariable.cs
├── ImplMap.cs
├── Importer.cs
├── InterfaceImpl.cs
├── MD
│ ├── BlobStream.cs
│ ├── CodedToken.cs
│ ├── ColumnInfo.cs
│ ├── ColumnSize.cs
│ ├── ComImageFlags.cs
│ ├── CompressedMetadata.cs
│ ├── CustomDotNetStream.cs
│ ├── DotNetStream.cs
│ ├── DotNetTableSizes.cs
│ ├── ENCMetadata.cs
│ ├── GuidStream.cs
│ ├── HeapType.cs
│ ├── IRowReaders.cs
│ ├── ImageCor20Header.cs
│ ├── MDHeaderRuntimeVersion.cs
│ ├── MDStreamFlags.cs
│ ├── MDTable.cs
│ ├── Metadata.cs
│ ├── MetadataBase.cs
│ ├── MetadataFactory.cs
│ ├── MetadataHeader.cs
│ ├── PdbStream.cs
│ ├── RawRowEqualityComparer.cs
│ ├── RawTableRows.cs
│ ├── RidList.cs
│ ├── StorageFlags.cs
│ ├── StreamHeader.cs
│ ├── StringsStream.cs
│ ├── Table.cs
│ ├── TableInfo.cs
│ ├── TablesStream.cs
│ ├── TablesStream_Read.cs
│ └── USStream.cs
├── MDToken.cs
├── ManifestResource.cs
├── ManifestResourceAttributes.cs
├── MarshalBlobReader.cs
├── MarshalType.cs
├── MemberFinder.cs
├── MemberMDInitializer.cs
├── MemberRef.cs
├── MethodAttributes.cs
├── MethodDef.cs
├── MethodExportInfo.cs
├── MethodExportInfoProvider.cs
├── MethodImplAttributes.cs
├── MethodOverride.cs
├── MethodSemanticsAttributes.cs
├── MethodSpec.cs
├── ModuleContext.cs
├── ModuleCreationOptions.cs
├── ModuleDef.cs
├── ModuleDefMD.cs
├── ModuleKind.cs
├── ModuleLoader.cs
├── ModuleRef.cs
├── NativeType.cs
├── NullResolver.cs
├── PInvokeAttributes.cs
├── ParamAttributes.cs
├── ParamDef.cs
├── ParameterList.cs
├── Pdb
│ ├── CustomDebugInfoGuids.cs
│ ├── DataReaderFactoryUtils.cs
│ ├── Dss
│ │ ├── ComInterfaces.cs
│ │ ├── DataReaderIStream.cs
│ │ ├── MDEmitter.cs
│ │ ├── MetaDataImport.cs
│ │ ├── ReaderMetaDataImport.cs
│ │ ├── StreamIStream.cs
│ │ ├── SymbolDocumentImpl.cs
│ │ ├── SymbolDocumentWriter.cs
│ │ ├── SymbolMethodImpl.cs
│ │ ├── SymbolNamespaceImpl.cs
│ │ ├── SymbolReaderImpl.cs
│ │ ├── SymbolReaderWriterFactory.cs
│ │ ├── SymbolScopeImpl.cs
│ │ ├── SymbolVariableImpl.cs
│ │ └── SymbolWriterImpl.cs
│ ├── IMAGE_DEBUG_DIRECTORY.cs
│ ├── Managed
│ │ ├── DbiDocument.cs
│ │ ├── DbiFunction.cs
│ │ ├── DbiModule.cs
│ │ ├── DbiNamespace.cs
│ │ ├── DbiScope.cs
│ │ ├── DbiVariable.cs
│ │ ├── ModuleStreamType.cs
│ │ ├── MsfStream.cs
│ │ ├── NumericLeaf.cs
│ │ ├── NumericReader.cs
│ │ ├── PdbAddress.cs
│ │ ├── PdbException.cs
│ │ ├── PdbReader.cs
│ │ ├── SymbolReaderFactory.cs
│ │ └── SymbolType.cs
│ ├── PdbConstant.cs
│ ├── PdbCustomDebugInfo.cs
│ ├── PdbDocument.cs
│ ├── PdbDocumentConstants.cs
│ ├── PdbFileKind.cs
│ ├── PdbImport.cs
│ ├── PdbLocal.cs
│ ├── PdbLocalAttributes.cs
│ ├── PdbMethod.cs
│ ├── PdbReaderContext.cs
│ ├── PdbReaderOptions.cs
│ ├── PdbScope.cs
│ ├── PdbState.cs
│ ├── PdbUtils.cs
│ ├── Portable
│ │ ├── DocumentNameReader.cs
│ │ ├── ImportDefinitionKindUtils.cs
│ │ ├── ImportScopeBlobReader.cs
│ │ ├── ImportScopeBlobWriter.cs
│ │ ├── ListCache.cs
│ │ ├── LocalConstantSigBlobReader.cs
│ │ ├── LocalConstantSigBlobWriter.cs
│ │ ├── PortablePdbCustomDebugInfoReader.cs
│ │ ├── PortablePdbCustomDebugInfoWriter.cs
│ │ ├── PortablePdbReader.cs
│ │ ├── SequencePointConstants.cs
│ │ ├── SymbolDocumentImpl.cs
│ │ ├── SymbolMethodImpl.cs
│ │ ├── SymbolReaderFactory.cs
│ │ ├── SymbolScopeImpl.cs
│ │ └── SymbolVariableImpl.cs
│ ├── SequencePoint.cs
│ ├── SymbolReaderFactory.cs
│ ├── Symbols
│ │ ├── SymbolAsyncStepInfo.cs
│ │ ├── SymbolDocument.cs
│ │ ├── SymbolMethod.cs
│ │ ├── SymbolNamespace.cs
│ │ ├── SymbolReader.cs
│ │ ├── SymbolScope.cs
│ │ ├── SymbolSequencePoint.cs
│ │ └── SymbolVariable.cs
│ └── WindowsPdb
│ │ ├── CorSymVarFlag.cs
│ │ ├── CustomDebugInfoConstants.cs
│ │ ├── PdbCustomDebugInfoReader.cs
│ │ ├── PdbCustomDebugInfoWriter.cs
│ │ ├── PseudoCustomDebugInfoFactory.cs
│ │ ├── SymbolWriter.cs
│ │ └── WindowsPdbWriter.cs
├── PropertyAttributes.cs
├── PropertyDef.cs
├── PublicKey.cs
├── PublicKeyBase.cs
├── PublicKeyToken.cs
├── RecursionCounter.cs
├── ReflectionExtensions.cs
├── ResolveException.cs
├── Resolver.cs
├── Resource.cs
├── ResourceCollection.cs
├── Resources
│ ├── BuiltInResourceData.cs
│ ├── IResourceData.cs
│ ├── ResourceBinaryWriter.cs
│ ├── ResourceDataFactory.cs
│ ├── ResourceElement.cs
│ ├── ResourceElementSet.cs
│ ├── ResourceReader.cs
│ ├── ResourceReaderType.cs
│ ├── ResourceTypeCode.cs
│ ├── ResourceWriter.cs
│ ├── UserResourceData.cs
│ └── UserResourceType.cs
├── SecurityAction.cs
├── SecurityAttribute.cs
├── SerializationType.cs
├── SigComparer.cs
├── SignatureReader.cs
├── StandAloneSig.cs
├── StrongNameKey.cs
├── StrongNameSigner.cs
├── TIAHelper.cs
├── TypeAttributes.cs
├── TypeDef.cs
├── TypeDefFinder.cs
├── TypeHelper.cs
├── TypeNameParser.cs
├── TypeRef.cs
├── TypeSig.cs
├── TypeSpec.cs
├── UTF8String.cs
├── Utils.cs
├── VTableFixups.cs
├── VariantType.cs
├── WinMDHelpers.cs
├── WinMDStatus.cs
└── Writer
│ ├── ArrayWriter.cs
│ ├── BlobHeap.cs
│ ├── ByteArrayChunk.cs
│ ├── ChecksumAlgorithm.cs
│ ├── ChunkList.cs
│ ├── ChunkListBase.cs
│ ├── CustomAttributeWriter.cs
│ ├── DataReaderChunk.cs
│ ├── DataReaderHeap.cs
│ ├── DataWriter.cs
│ ├── DebugDirectory.cs
│ ├── DeclSecurityWriter.cs
│ ├── Extensions.cs
│ ├── GuidHeap.cs
│ ├── Hasher.cs
│ ├── HeapBase.cs
│ ├── IChunk.cs
│ ├── IHeap.cs
│ ├── IOffsetHeap.cs
│ ├── IWriterError.cs
│ ├── ImageCor20Header.cs
│ ├── ImportAddressTable.cs
│ ├── ImportDirectory.cs
│ ├── MDTable.cs
│ ├── MDTableWriter.cs
│ ├── ManagedExportsWriter.cs
│ ├── MarshalBlobWriter.cs
│ ├── MaxStackCalculator.cs
│ ├── Metadata.cs
│ ├── MetadataErrorContext.cs
│ ├── MetadataEvent.cs
│ ├── MetadataHeader.cs
│ ├── MethodBody.cs
│ ├── MethodBodyChunks.cs
│ ├── MethodBodyWriter.cs
│ ├── MethodBodyWriterBase.cs
│ ├── ModuleWriter.cs
│ ├── ModuleWriterBase.cs
│ ├── ModuleWriterEvent.cs
│ ├── ModuleWriterException.cs
│ ├── NativeModuleWriter.cs
│ ├── NetResources.cs
│ ├── NormalMetadata.cs
│ ├── PEHeaders.cs
│ ├── PESection.cs
│ ├── PdbHeap.cs
│ ├── PortablePdbConstants.cs
│ ├── PreserveTokensMetadata.cs
│ ├── RelocDirectory.cs
│ ├── RoslynContentIdProvider.cs
│ ├── SectionSizes.cs
│ ├── SerializerMethodContext.cs
│ ├── SignatureWriter.cs
│ ├── StartupStub.cs
│ ├── StringsHeap.cs
│ ├── StrongNameSignature.cs
│ ├── TablesHeap.cs
│ ├── USHeap.cs
│ ├── UniqueChunkList.cs
│ ├── Win32ResourcesChunk.cs
│ └── WriterUtils.cs
├── HandleProcessCorruptedStateExceptionsAttribute.cs
├── IO
├── AlignedByteArrayDataStream.cs
├── AlignedNativeMemoryDataStream.cs
├── ByteArrayDataReaderFactory.cs
├── DataReader.cs
├── DataReaderFactory.cs
├── DataReaderFactoryFactory.cs
├── DataReaderStream.cs
├── DataStream.cs
├── DataStreamFactory.cs
├── EmptyDataStream.cs
├── FileOffset.cs
├── FileSection.cs
├── IFileSection.cs
├── IOExtensions.cs
├── MemoryMappedDataReaderFactory.cs
├── NativeMemoryDataReaderFactory.cs
├── UnalignedByteArrayDataStream.cs
└── UnalignedNativeMemoryDataStream.cs
├── PE
├── Characteristics.cs
├── DllCharacteristics.cs
├── IImageOptionalHeader.cs
├── IPEImage.cs
├── IPEType.cs
├── ImageDataDirectory.cs
├── ImageDebugDirectory.cs
├── ImageDebugType.cs
├── ImageDosHeader.cs
├── ImageFileHeader.cs
├── ImageNTHeaders.cs
├── ImageOptionalHeader32.cs
├── ImageOptionalHeader64.cs
├── ImageSectionHeader.cs
├── Machine.cs
├── PEExtensions.cs
├── PEImage.cs
├── PEInfo.cs
├── ProcessorArchUtils.cs
├── RVA.cs
└── Subsystem.cs
├── Settings.cs
├── Threading
├── ICancellationToken.cs
└── Lock.cs
├── Utils
├── ArrayEmpty.cs
├── CollectionDebugView.cs
├── ILazyList.cs
├── LazyList.cs
├── SimpleLazyList.cs
└── UserValue.cs
├── W32Resources
├── ResourceData.cs
├── ResourceDirectory.cs
├── ResourceDirectoryEntry.cs
├── ResourceName.cs
└── Win32Resources.cs
└── dnlib.csproj
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: GitHub CI
2 | on:
3 | push:
4 | paths:
5 | - '.github/workflows/**'
6 | - 'Examples/**'
7 | - 'src/**'
8 | - '!**/*.md'
9 | branches:
10 | - master
11 | pull_request:
12 | paths:
13 | - 'Examples/**'
14 | - 'src/**'
15 | - '!**/*.md'
16 | branches:
17 | - master
18 | release:
19 | types: released
20 |
21 | env:
22 | CI_REQ_DOTNET_SDK_VER: 6.0.100
23 |
24 | jobs:
25 | build-windows:
26 | name: Build (Windows)
27 | runs-on: windows-latest
28 |
29 | steps:
30 | - uses: actions/checkout@v3
31 |
32 | - uses: actions/setup-dotnet@v3
33 | with:
34 | dotnet-version: ${{env.CI_REQ_DOTNET_SDK_VER}}
35 |
36 | - name: Build
37 | shell: pwsh
38 | run: |
39 | $msbuildPath = Split-Path (& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -requires Microsoft.Component.MSBuild -find MSBuild\Current\Bin\amd64\MSBuild.exe | Select-Object -First 1) -Parent
40 | $env:PATH = $msbuildPath + ';' + $env:PATH
41 | .\build.ps1
42 |
43 | - name: upload-artifact doesn't support wildcards
44 | if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')
45 | shell: pwsh
46 | run: |
47 | New-Item -ItemType Directory nuget_files > $null
48 | Copy-Item src\bin\Release\*.*nupkg nuget_files
49 |
50 | - uses: actions/upload-artifact@v4
51 | if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')
52 | with:
53 | name: nupkg
54 | path: nuget_files
55 | if-no-files-found: error
56 |
57 | - name: Upload to nuget.org if it's a new release
58 | if: startsWith(github.ref, 'refs/tags/')
59 | shell: pwsh
60 | run: |
61 | Invoke-WebRequest -Uri https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -UseBasicParsing -OutFile nuget.exe
62 | Get-ChildItem src\bin\Release\dnlib.*.nupkg | ForEach-Object { .\nuget.exe push $_.FullName -ApiKey ${{secrets.NUGET_APIKEY}} -NonInteractive -Source https://api.nuget.org/v3/index.json }
63 |
64 | # Make sure it builds on Linux too
65 | build-ubuntu:
66 | name: Build (Ubuntu)
67 | runs-on: ubuntu-latest
68 |
69 | steps:
70 | - uses: actions/checkout@v3
71 |
72 | - uses: actions/setup-dotnet@v3
73 | with:
74 | dotnet-version: ${{env.CI_REQ_DOTNET_SDK_VER}}
75 |
76 | - name: Build
77 | shell: pwsh
78 | run: ./build.ps1
79 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/
2 | .vscode/
3 | bin/
4 | obj/
5 |
--------------------------------------------------------------------------------
/Examples/Example1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 |
4 | namespace dnlib.Examples {
5 | // This example will open mscorlib.dll and then print out all types
6 | // in the assembly, including the number of methods, fields, properties
7 | // and events each type has.
8 | public class Example1 {
9 | public static void Run() {
10 | // Load mscorlib.dll
11 | var filename = typeof(void).Module.FullyQualifiedName;
12 | var mod = ModuleDefMD.Load(filename);
13 |
14 | int totalNumTypes = 0;
15 | // mod.Types only returns non-nested types.
16 | // mod.GetTypes() returns all types, including nested types.
17 | foreach (var type in mod.GetTypes()) {
18 | totalNumTypes++;
19 | Console.WriteLine();
20 | Console.WriteLine("Type: {0}", type.FullName);
21 | if (type.BaseType is not null)
22 | Console.WriteLine(" Base type: {0}", type.BaseType.FullName);
23 |
24 | Console.WriteLine(" Methods: {0}", type.Methods.Count);
25 | Console.WriteLine(" Fields: {0}", type.Fields.Count);
26 | Console.WriteLine(" Properties: {0}", type.Properties.Count);
27 | Console.WriteLine(" Events: {0}", type.Events.Count);
28 | Console.WriteLine(" Nested types: {0}", type.NestedTypes.Count);
29 |
30 | if (type.Interfaces.Count > 0) {
31 | Console.WriteLine(" Interfaces:");
32 | foreach (var iface in type.Interfaces)
33 | Console.WriteLine(" {0}", iface.Interface.FullName);
34 | }
35 | }
36 | Console.WriteLine();
37 | Console.WriteLine("Total number of types: {0}", totalNumTypes);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Examples/Example5.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using dnlib.DotNet;
4 |
5 | namespace dnlib.Examples {
6 | ///
7 | /// Dumps all PE sections to disk
8 | ///
9 | public class Example5 {
10 | public static void Run() {
11 | string sectionFileName = @"c:\section{0}.bin";
12 |
13 | // Open the current mscorlib
14 | var mod = ModuleDefMD.Load(typeof(int).Module);
15 |
16 | // Get PE image interface
17 | var peImage = mod.Metadata.PEImage;
18 |
19 | // Print some info
20 | Console.WriteLine("Machine: {0}", peImage.ImageNTHeaders.FileHeader.Machine);
21 | Console.WriteLine("Characteristics: {0}", peImage.ImageNTHeaders.FileHeader.Characteristics);
22 |
23 | Console.WriteLine("Dumping all sections");
24 | for (int i = 0; i < peImage.ImageSectionHeaders.Count; i++) {
25 | var section = peImage.ImageSectionHeaders[i];
26 |
27 | // Create a reader for the whole section
28 | var reader = peImage.CreateReader(section.VirtualAddress, section.SizeOfRawData);
29 |
30 | // Write the data to disk
31 | var fileName = string.Format(sectionFileName, i);
32 | Console.WriteLine("Dumping section {0} to file {1}", section.DisplayName, fileName);
33 | File.WriteAllBytes(fileName, reader.ToArray());
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Examples/Example7.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using dnlib.DotNet;
5 | using dnlib.DotNet.Emit;
6 |
7 | namespace dnlib.Examples {
8 | public class Example7 {
9 | public static void Run() => new Example7().DoIt();
10 |
11 | void DoIt() {
12 | var test1 = new OpCode(
13 | "test1", 0xf0, 0x00, OperandType.InlineNone, FlowControl.Next, StackBehaviour.Push0, StackBehaviour.Pop0);
14 | var test2 = new OpCode(
15 | "test2", 0xf0, 0x01, OperandType.InlineBrTarget, FlowControl.Branch, StackBehaviour.Push0, StackBehaviour.Pop0);
16 | var test3 = new OpCode(
17 | "test3", 0xf0, 0x02, OperandType.InlineString, FlowControl.Next, StackBehaviour.Push1, StackBehaviour.Pop0);
18 |
19 | var ctx = new ModuleContext();
20 |
21 | ctx.RegisterExperimentalOpCode(test1);
22 | ctx.RegisterExperimentalOpCode(test2);
23 | ctx.RegisterExperimentalOpCode(test3);
24 |
25 | var mod = ModuleDefMD.Load(typeof(Example7).Module, ctx);
26 | var body = mod.Types.Single(x => x.Name == nameof(Example7)).Methods.Single(x => x.Name == nameof(CustomCil)).Body;
27 |
28 | Console.WriteLine("Original:");
29 | foreach (var insn in body.Instructions)
30 | Console.WriteLine("{0} (0x{1:X4})", insn, insn.OpCode.Value);
31 | Console.WriteLine();
32 |
33 | var code = body.Instructions;
34 |
35 | code.Clear();
36 |
37 | var label = OpCodes.Nop.ToInstruction();
38 |
39 | code.Add(test1.ToInstruction());
40 | code.Add(OpCodes.Nop.ToInstruction());
41 | code.Add(label);
42 | code.Add(OpCodes.Ret.ToInstruction());
43 | code.Add(test2.ToInstruction(label));
44 | code.Add(test3.ToInstruction("foo"));
45 |
46 | Console.WriteLine("Modified:");
47 | foreach (var insn in body.Instructions)
48 | Console.WriteLine("{0} (0x{1:X4})", insn, insn.OpCode.Value);
49 | Console.WriteLine();
50 |
51 | using (var stream = new MemoryStream()) {
52 | mod.Write(stream);
53 |
54 | stream.Position = 0;
55 |
56 | mod = ModuleDefMD.Load(stream, ctx);
57 | body = mod.Types.Single(x => x.Name == nameof(Example7)).Methods.Single(x => x.Name == nameof(CustomCil)).Body;
58 |
59 | Console.WriteLine("Roundtripped:");
60 | foreach (var insn in body.Instructions)
61 | Console.WriteLine("{0} (0x{1:X4})", insn, insn.OpCode.Value);
62 | Console.WriteLine();
63 | }
64 | }
65 |
66 | void CustomCil() {
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Examples/Examples.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0;net45
5 | Exe
6 | false
7 | latest
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Examples/Program.cs:
--------------------------------------------------------------------------------
1 | namespace dnlib.Examples {
2 | class Program {
3 | static void Main(string[] args) {
4 | // Just uncomment whatever you want to debug
5 | // Example1.Run();
6 | // Example2.Run();
7 | // Example3.Run();
8 | // Example4.Run();
9 | // Example5.Run();
10 | // Example6.Run();
11 | Example7.Run();
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (C) 2012-2019 de4dot@gmail.com
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/build.ps1:
--------------------------------------------------------------------------------
1 | param([switch]$NoMsbuild)
2 |
3 | $ErrorActionPreference = 'Stop'
4 |
5 | $configuration = 'Release'
6 |
7 | #
8 | # dotnet build isn't used because it can't build net35 tfms
9 | #
10 |
11 | $env:NoTargetFrameworkNet35 = ''
12 |
13 | $useMsbuild = $IsWindows -or $IsWindows -eq $null
14 | if ($NoMsbuild) {
15 | $useMsbuild = $false
16 | }
17 |
18 | if (!$useMsbuild) {
19 | # There are currently no net35 reference assemblies on nuget
20 | $env:NoTargetFrameworkNet35 = 'true'
21 | }
22 |
23 | if ($useMsbuild) {
24 | msbuild -v:m -restore -t:Build -p:Configuration=$configuration
25 | if ($LASTEXITCODE) { exit $LASTEXITCODE }
26 | msbuild -v:m -t:Pack -p:Configuration=$configuration src/dnlib.csproj
27 | if ($LASTEXITCODE) { exit $LASTEXITCODE }
28 | }
29 | else {
30 | dotnet build -v:m -c $configuration
31 | if ($LASTEXITCODE) { exit $LASTEXITCODE }
32 | dotnet pack -v:m -c $configuration src/dnlib.csproj
33 | if ($LASTEXITCODE) { exit $LASTEXITCODE }
34 | }
35 |
36 | $env:NoTargetFrameworkNet35 = ''
37 |
--------------------------------------------------------------------------------
/dnlib.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29318.209
5 | MinimumVisualStudioVersion = 16.0.29318.209
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dnlib", "src\dnlib.csproj", "{FDFC1237-143F-4919-8318-4926901F4639}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples", "Examples\Examples.csproj", "{F27E72B5-C4BD-40BF-AD19-4C8A99B55872}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {FDFC1237-143F-4919-8318-4926901F4639}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {FDFC1237-143F-4919-8318-4926901F4639}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {FDFC1237-143F-4919-8318-4926901F4639}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {FDFC1237-143F-4919-8318-4926901F4639}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {49902A67-E85B-44E8-9C4F-26F8854AA894}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/dnlib.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xd4d/dnlib/c78d296c522aae0520df2afd825d48266321cf36/dnlib.snk
--------------------------------------------------------------------------------
/src/DefaultDllImportSearchPathsAttribute.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | #if NET35
4 | namespace System.Runtime.InteropServices {
5 | [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Method, AllowMultiple = false)]
6 | sealed class DefaultDllImportSearchPathsAttribute : Attribute {
7 | public DefaultDllImportSearchPathsAttribute(DllImportSearchPath paths) => _paths = paths;
8 | public DllImportSearchPath Paths => _paths;
9 | internal DllImportSearchPath _paths;
10 | }
11 |
12 | [Flags]
13 | enum DllImportSearchPath {
14 | LegacyBehavior = 0,
15 | AssemblyDirectory = 2,
16 | UseDllDirectoryForDependencies = 0x100,
17 | ApplicationDirectory = 0x200,
18 | UserDirectories = 0x400,
19 | System32 = 0x800,
20 | SafeDirectories = 0x1000,
21 | }
22 | }
23 | #endif
24 |
--------------------------------------------------------------------------------
/src/DotNet/AllTypesHelper.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Collections.Generic;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Returns types without getting stuck in an infinite loop
8 | ///
9 | readonly struct AllTypesHelper {
10 | ///
11 | /// Gets a list of all types and nested types
12 | ///
13 | /// A list of types
14 | public static IEnumerable Types(IEnumerable types) {
15 | var visited = new Dictionary();
16 | var stack = new Stack>();
17 | if (types is not null)
18 | stack.Push(types.GetEnumerator());
19 | while (stack.Count > 0) {
20 | var enumerator = stack.Pop();
21 | while (enumerator.MoveNext()) {
22 | var type = enumerator.Current;
23 | if (visited.ContainsKey(type))
24 | continue;
25 | visited[type] = true;
26 | yield return type;
27 | if (type.NestedTypes.Count > 0) {
28 | stack.Push(enumerator);
29 | enumerator = type.NestedTypes.GetEnumerator();
30 | }
31 | }
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/DotNet/AssemblyAttributes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Assembly flags from Assembly.Flags column.
8 | ///
9 | /// See CorHdr.h/CorAssemblyFlags
10 | [Flags]
11 | public enum AssemblyAttributes : uint {
12 | /// No flags set
13 | None = 0,
14 |
15 | /// The assembly ref holds the full (unhashed) public key.
16 | PublicKey = 1,
17 |
18 | /// Processor Architecture unspecified
19 | PA_None = 0x0000,
20 | /// Processor Architecture: neutral (PE32)
21 | PA_MSIL = 0x0010,
22 | /// Processor Architecture: x86 (PE32)
23 | PA_x86 = 0x0020,
24 | /// Processor Architecture: Itanium (PE32+)
25 | PA_IA64 = 0x0030,
26 | /// Processor Architecture: AMD X64 (PE32+)
27 | PA_AMD64 = 0x0040,
28 | /// Processor Architecture: ARM (PE32)
29 | PA_ARM = 0x0050,
30 | /// Processor Architecture: ARM64 (PE32+)
31 | PA_ARM64 = 0x0060,
32 | /// applies to any platform but cannot run on any (e.g. reference assembly), should not have "specified" set
33 | PA_NoPlatform = 0x0070,
34 | /// Propagate PA flags to AssemblyRef record
35 | PA_Specified = 0x0080,
36 | /// Bits describing the processor architecture
37 | PA_Mask = 0x0070,
38 | /// Bits describing the PA incl. Specified
39 | PA_FullMask = 0x00F0,
40 | /// NOT A FLAG, shift count in PA flags <--> index conversion
41 | PA_Shift = 0x0004,
42 |
43 | /// From "DebuggableAttribute".
44 | EnableJITcompileTracking = 0x8000,
45 | /// From "DebuggableAttribute".
46 | DisableJITcompileOptimizer = 0x4000,
47 |
48 | /// The assembly can be retargeted (at runtime) to an assembly from a different publisher.
49 | Retargetable = 0x0100,
50 |
51 | ///
52 | ContentType_Default = 0x0000,
53 | ///
54 | ContentType_WindowsRuntime = 0x0200,
55 | /// Bits describing ContentType
56 | ContentType_Mask = 0x0E00,
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/DotNet/AssemblyHashAlgorithm.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet {
4 | ///
5 | /// Any ALG_CLASS_HASH type in WinCrypt.h can be used by Microsoft's CLI implementation
6 | ///
7 | public enum AssemblyHashAlgorithm : uint {
8 | ///
9 | None = 0,
10 | ///
11 | MD2 = 0x8001,
12 | ///
13 | MD4 = 0x8002,
14 | /// This is a reserved value in the CLI
15 | MD5 = 0x8003,
16 | /// The only algorithm supported by the CLI
17 | SHA1 = 0x8004,
18 | ///
19 | MAC = 0x8005,
20 | ///
21 | SSL3_SHAMD5 = 0x8008,
22 | ///
23 | HMAC = 0x8009,
24 | ///
25 | TLS1PRF = 0x800A,
26 | ///
27 | HASH_REPLACE_OWF = 0x800B,
28 | ///
29 | SHA_256 = 0x800C,
30 | ///
31 | SHA_384 = 0x800D,
32 | ///
33 | SHA_512 = 0x800E,
34 | }
35 |
36 | public static partial class Extensions {
37 | internal static string GetName(this AssemblyHashAlgorithm hashAlg) =>
38 | hashAlg switch {
39 | AssemblyHashAlgorithm.MD2 => null,
40 | AssemblyHashAlgorithm.MD4 => null,
41 | AssemblyHashAlgorithm.MD5 => "MD5",
42 | AssemblyHashAlgorithm.SHA1 => "SHA1",
43 | AssemblyHashAlgorithm.MAC => null,
44 | AssemblyHashAlgorithm.SSL3_SHAMD5 => null,
45 | AssemblyHashAlgorithm.HMAC => null,
46 | AssemblyHashAlgorithm.TLS1PRF => null,
47 | AssemblyHashAlgorithm.HASH_REPLACE_OWF => null,
48 | AssemblyHashAlgorithm.SHA_256 => "SHA256",
49 | AssemblyHashAlgorithm.SHA_384 => "SHA384",
50 | AssemblyHashAlgorithm.SHA_512 => "SHA512",
51 | _ => null,
52 | };
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/DotNet/CallingConvention.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// See CorHdr.h/CorCallingConvention
8 | ///
9 | [Flags]
10 | public enum CallingConvention : byte {
11 | /// The managed calling convention
12 | Default = 0x0,
13 | ///
14 | C = 0x1,
15 | ///
16 | StdCall = 0x2,
17 | ///
18 | ThisCall = 0x3,
19 | ///
20 | FastCall = 0x4,
21 | ///
22 | VarArg = 0x5,
23 | ///
24 | Field = 0x6,
25 | ///
26 | LocalSig = 0x7,
27 | ///
28 | Property = 0x8,
29 | /// Unmanaged calling convention encoded as modopts
30 | Unmanaged = 0x9,
31 | /// generic method instantiation
32 | GenericInst = 0xA,
33 | /// used ONLY for 64bit vararg PInvoke calls
34 | NativeVarArg = 0xB,
35 |
36 | /// Calling convention is bottom 4 bits
37 | Mask = 0x0F,
38 |
39 | /// Generic method
40 | Generic = 0x10,
41 | /// Method needs a 'this' parameter
42 | HasThis = 0x20,
43 | /// 'this' parameter is the first arg if set (else it's hidden)
44 | ExplicitThis = 0x40,
45 | /// Used internally by the CLR
46 | ReservedByCLR = 0x80,
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/DotNet/Emit/ExceptionHandler.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Emit {
4 | ///
5 | /// A CIL method exception handler
6 | ///
7 | public sealed class ExceptionHandler {
8 | ///
9 | /// First instruction of try block
10 | ///
11 | public Instruction TryStart;
12 |
13 | ///
14 | /// One instruction past the end of try block or null if it ends at the end
15 | /// of the method.
16 | ///
17 | public Instruction TryEnd;
18 |
19 | ///
20 | /// Start of filter handler or null if none. The end of filter handler is
21 | /// always .
22 | ///
23 | public Instruction FilterStart;
24 |
25 | ///
26 | /// First instruction of try handler block
27 | ///
28 | public Instruction HandlerStart;
29 |
30 | ///
31 | /// One instruction past the end of try handler block or null if it ends at the end
32 | /// of the method.
33 | ///
34 | public Instruction HandlerEnd;
35 |
36 | ///
37 | /// The catch type if is
38 | ///
39 | public ITypeDefOrRef CatchType;
40 |
41 | ///
42 | /// Type of exception handler clause
43 | ///
44 | public ExceptionHandlerType HandlerType;
45 |
46 | ///
47 | /// Checks if it's a `catch` handler
48 | ///
49 | public bool IsCatch => ((uint)HandlerType & 7) == (uint)ExceptionHandlerType.Catch;
50 |
51 | ///
52 | /// Checks if it's a `filter` handler
53 | ///
54 | public bool IsFilter => (HandlerType & ExceptionHandlerType.Filter) != 0;
55 |
56 | ///
57 | /// Checks if it's a `finally` handler
58 | ///
59 | public bool IsFinally => (HandlerType & ExceptionHandlerType.Finally) != 0;
60 |
61 | ///
62 | /// Checks if it's a `fault` handler
63 | ///
64 | public bool IsFault => (HandlerType & ExceptionHandlerType.Fault) != 0;
65 |
66 | ///
67 | /// Default constructor
68 | ///
69 | public ExceptionHandler() {
70 | }
71 |
72 | ///
73 | /// Constructor
74 | ///
75 | /// Exception clause type
76 | public ExceptionHandler(ExceptionHandlerType handlerType) => HandlerType = handlerType;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/DotNet/Emit/ExceptionHandlerType.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet.Emit {
6 | ///
7 | /// Type of exception handler. See CorHdr.h/CorExceptionFlag
8 | ///
9 | [Flags]
10 | public enum ExceptionHandlerType {
11 | ///
12 | Catch = 0x0000,
13 | ///
14 | Filter = 0x0001,
15 | ///
16 | Finally = 0x0002,
17 | ///
18 | Fault = 0x0004,
19 | ///
20 | Duplicated = 0x0008,
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/DotNet/Emit/Extensions.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Emit {
4 | ///
5 | /// Extension methods
6 | ///
7 | public static partial class Extensions {
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/DotNet/Emit/FlowControl.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Emit {
4 | ///
5 | /// CIL opcode flow control
6 | ///
7 | public enum FlowControl {
8 | ///
9 | Branch,
10 | ///
11 | Break,
12 | ///
13 | Call,
14 | ///
15 | Cond_Branch,
16 | ///
17 | Meta,
18 | ///
19 | Next,
20 | ///
21 | Phi,
22 | ///
23 | Return,
24 | ///
25 | Throw,
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/DotNet/Emit/InvalidMethodException.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Runtime.Serialization;
5 |
6 | namespace dnlib.DotNet.Emit {
7 | ///
8 | /// Thrown when invalid data is detected while parsing a .NET method
9 | ///
10 | [Serializable]
11 | public class InvalidMethodException : Exception {
12 | ///
13 | /// Default constructor
14 | ///
15 | public InvalidMethodException() {
16 | }
17 |
18 | ///
19 | /// Constructor
20 | ///
21 | /// Error message
22 | public InvalidMethodException(string msg)
23 | : base(msg) {
24 | }
25 |
26 | ///
27 | /// Constructor
28 | ///
29 | /// Error message
30 | /// The inner exception or null if none
31 | public InvalidMethodException(string msg, Exception innerException)
32 | : base(msg, innerException) {
33 | }
34 |
35 | ///
36 | /// Constructor
37 | ///
38 | ///
39 | ///
40 | protected InvalidMethodException(SerializationInfo info, StreamingContext context)
41 | : base(info, context) {
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/DotNet/Emit/OpCodeType.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Emit {
4 | ///
5 | /// CIL opcode type
6 | ///
7 | public enum OpCodeType : byte {
8 | ///
9 | Annotation,
10 | ///
11 | Macro,
12 | ///
13 | Nternal,
14 | ///
15 | Objmodel,
16 | ///
17 | Prefix,
18 | ///
19 | Primitive,
20 | ///
21 | Experimental,
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/DotNet/Emit/OperandType.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using dnlib.DotNet.MD;
4 |
5 | namespace dnlib.DotNet.Emit {
6 | ///
7 | /// CIL opcode operand type
8 | ///
9 | public enum OperandType : byte {
10 | /// 4-byte relative instruction offset
11 | InlineBrTarget,
12 | /// 4-byte field token ( or )
13 | InlineField,
14 | /// int32
15 | InlineI,
16 | /// int64
17 | InlineI8,
18 | /// 4-byte method token (,
19 | /// or )
20 | InlineMethod,
21 | /// No operand
22 | InlineNone,
23 | /// Never used
24 | InlinePhi,
25 | /// 64-bit real
26 | InlineR,
27 | ///
28 | NOT_USED_8,
29 | /// 4-byte method sig token ()
30 | InlineSig,
31 | /// 4-byte string token (0x70xxxxxx)
32 | InlineString,
33 | /// 4-byte count N followed by N 4-byte relative instruction offsets
34 | InlineSwitch,
35 | /// 4-byte token (, ,
36 | /// , , ,
37 | /// or )
38 | InlineTok,
39 | /// 4-byte type token (, or
40 | /// )
41 | InlineType,
42 | /// 2-byte param/local index
43 | InlineVar,
44 | /// 1-byte relative instruction offset
45 | ShortInlineBrTarget,
46 | /// 1-byte sbyte () or byte (the rest)
47 | ShortInlineI,
48 | /// 32-bit real
49 | ShortInlineR,
50 | /// 1-byte param/local index
51 | ShortInlineVar,
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/DotNet/Emit/StackBehaviour.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Emit {
4 | ///
5 | /// CIL opcode stack behavior
6 | ///
7 | public enum StackBehaviour : byte {
8 | ///
9 | Pop0,
10 | ///
11 | Pop1,
12 | ///
13 | Pop1_pop1,
14 | ///
15 | Popi,
16 | ///
17 | Popi_pop1,
18 | ///
19 | Popi_popi,
20 | ///
21 | Popi_popi8,
22 | ///
23 | Popi_popi_popi,
24 | ///
25 | Popi_popr4,
26 | ///
27 | Popi_popr8,
28 | ///
29 | Popref,
30 | ///
31 | Popref_pop1,
32 | ///
33 | Popref_popi,
34 | ///
35 | Popref_popi_popi,
36 | ///
37 | Popref_popi_popi8,
38 | ///
39 | Popref_popi_popr4,
40 | ///
41 | Popref_popi_popr8,
42 | ///
43 | Popref_popi_popref,
44 | ///
45 | Push0,
46 | ///
47 | Push1,
48 | ///
49 | Push1_push1,
50 | ///
51 | Pushi,
52 | ///
53 | Pushi8,
54 | ///
55 | Pushr4,
56 | ///
57 | Pushr8,
58 | ///
59 | Pushref,
60 | ///
61 | Varpop,
62 | ///
63 | Varpush,
64 | ///
65 | Popref_popi_pop1,
66 | ///
67 | PopAll = 0xFF,
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/DotNet/EventAttributes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Event attributes, see CorHdr.h/CorEventAttr
8 | ///
9 | [Flags]
10 | public enum EventAttributes : ushort {
11 | /// event is special. Name describes how.
12 | SpecialName = 0x0200,
13 | /// Runtime(metadata internal APIs) should check name encoding.
14 | RTSpecialName = 0x0400,
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/DotNet/Extensions.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet {
4 | ///
5 | /// Extension methods
6 | ///
7 | public static partial class Extensions {
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/DotNet/FieldAttributes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Field flags, see CorHdr.h/CorFieldAttr
8 | ///
9 | [Flags]
10 | public enum FieldAttributes : ushort {
11 | /// member access mask - Use this mask to retrieve accessibility information.
12 | FieldAccessMask = 0x0007,
13 | /// Member not referenceable.
14 | PrivateScope = 0x0000,
15 | /// Member not referenceable.
16 | CompilerControlled = PrivateScope,
17 | /// Accessible only by the parent type.
18 | Private = 0x0001,
19 | /// Accessible by sub-types only in this Assembly.
20 | FamANDAssem = 0x0002,
21 | /// Accessibly by anyone in the Assembly.
22 | Assembly = 0x0003,
23 | /// Accessible only by type and sub-types.
24 | Family = 0x0004,
25 | /// Accessibly by sub-types anywhere, plus anyone in assembly.
26 | FamORAssem = 0x0005,
27 | /// Accessibly by anyone who has visibility to this scope.
28 | Public = 0x0006,
29 |
30 | /// Defined on type, else per instance.
31 | Static = 0x0010,
32 | /// Field may only be initialized, not written to after init.
33 | InitOnly = 0x0020,
34 | /// Value is compile time constant.
35 | Literal = 0x0040,
36 | /// Field does not have to be serialized when type is remoted.
37 | NotSerialized = 0x0080,
38 |
39 | /// field is special. Name describes how.
40 | SpecialName = 0x0200,
41 |
42 | /// Implementation is forwarded through pinvoke.
43 | PinvokeImpl = 0x2000,
44 |
45 | /// Runtime(metadata internal APIs) should check name encoding.
46 | RTSpecialName = 0x0400,
47 | /// Field has marshalling information.
48 | HasFieldMarshal = 0x1000,
49 | /// Field has default.
50 | HasDefault = 0x8000,
51 | /// Field has RVA.
52 | HasFieldRVA = 0x0100,
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/DotNet/FileAttributes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// File row flags. See CorHdr.h/CorFileFlags
8 | ///
9 | [Flags]
10 | public enum FileAttributes : uint {
11 | /// This is not a resource file
12 | ContainsMetadata = 0x0000,
13 | /// This is a resource file or other non-metadata-containing file
14 | ContainsNoMetadata = 0x0001,
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/DotNet/GenericParamAttributes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Generic parameter flags. See CorHdr.h/CorGenericParamAttr
8 | ///
9 | [Flags]
10 | public enum GenericParamAttributes : ushort {
11 | ///
12 | VarianceMask = 0x0003,
13 | ///
14 | NonVariant = 0x0000,
15 | ///
16 | Covariant = 0x0001,
17 | ///
18 | Contravariant = 0x0002,
19 |
20 | ///
21 | SpecialConstraintMask = 0x003C,
22 | ///
23 | NoSpecialConstraint = 0x0000,
24 | /// type argument must be a reference type
25 | ReferenceTypeConstraint = 0x0004,
26 | /// type argument must be a value type but not Nullable
27 | NotNullableValueTypeConstraint = 0x0008,
28 | /// type argument must have a public default constructor
29 | DefaultConstructorConstraint = 0x0010,
30 | /// type argument can be ByRefLike
31 | AllowByRefLike = 0x0020,
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/DotNet/GenericParamContext.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet {
4 | ///
5 | /// Generic parameter context
6 | ///
7 | public readonly struct GenericParamContext {
8 | ///
9 | /// Type context
10 | ///
11 | public readonly TypeDef Type;
12 |
13 | ///
14 | /// Method context
15 | ///
16 | public readonly MethodDef Method;
17 |
18 | ///
19 | /// true if and are both null
20 | ///
21 | public bool IsEmpty => Type is null && Method is null;
22 |
23 | ///
24 | /// Creates a new instance and initializes the
25 | /// field to 's
26 | /// and the field to .
27 | ///
28 | /// Method
29 | /// A new instance
30 | public static GenericParamContext Create(MethodDef method) {
31 | if (method is null)
32 | return new GenericParamContext();
33 | return new GenericParamContext(method.DeclaringType, method);
34 | }
35 |
36 | ///
37 | /// Creates a new instance and initializes the
38 | /// field to and the field
39 | /// to null
40 | ///
41 | /// Type
42 | /// A new instance
43 | public static GenericParamContext Create(TypeDef type) => new GenericParamContext(type);
44 |
45 | ///
46 | /// Constructor
47 | ///
48 | /// Type context
49 | public GenericParamContext(TypeDef type) {
50 | Type = type;
51 | Method = null;
52 | }
53 |
54 | ///
55 | /// Constructor. The field is set to null and NOT to
56 | /// 's . Use
57 | /// if you want that behavior.
58 | ///
59 | /// Method context
60 | public GenericParamContext(MethodDef method) {
61 | Type = null;
62 | Method = method;
63 | }
64 |
65 | ///
66 | /// Constructor
67 | ///
68 | /// Type context
69 | /// Method context
70 | public GenericParamContext(TypeDef type, MethodDef method) {
71 | Type = type;
72 | Method = method;
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/DotNet/ICustomAttribute.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Collections.Generic;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Custom attribute interface. Implemented by and
8 | ///
9 | ///
10 | public interface ICustomAttribute {
11 | ///
12 | /// Gets the attribute type
13 | ///
14 | ITypeDefOrRef AttributeType { get; }
15 |
16 | ///
17 | /// Gets the full name of the attribute type
18 | ///
19 | string TypeFullName { get; }
20 |
21 | ///
22 | /// Gets all named arguments (field and property values)
23 | ///
24 | IList NamedArguments { get; }
25 |
26 | ///
27 | /// true if is not empty
28 | ///
29 | bool HasNamedArguments { get; }
30 |
31 | ///
32 | /// Gets all s that are field arguments
33 | ///
34 | IEnumerable Fields { get; }
35 |
36 | ///
37 | /// Gets all s that are property arguments
38 | ///
39 | IEnumerable Properties { get; }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/DotNet/IDecrypters.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Collections.Generic;
4 | using dnlib.PE;
5 | using dnlib.DotNet.Emit;
6 |
7 | namespace dnlib.DotNet {
8 | ///
9 | /// Interface to decrypt methods
10 | ///
11 | public interface IMethodDecrypter {
12 | ///
13 | /// Gets the method's body
14 | ///
15 | /// Method rid
16 | /// The found in the method's Method row
17 | /// The method's parameters
18 | /// Generic parameter context
19 | /// Updated with the method's if this
20 | /// method returns true
21 | /// true if the method body was decrypted, false if the method isn't
22 | /// encrypted and the default body reader code should be used.
23 | bool GetMethodBody(uint rid, RVA rva, IList parameters, GenericParamContext gpContext, out MethodBody methodBody);
24 | }
25 |
26 | ///
27 | /// Interface to decrypt strings
28 | ///
29 | public interface IStringDecrypter {
30 | ///
31 | /// Reads a string
32 | ///
33 | /// String token
34 | /// A string or null if we should read it from the #US heap
35 | string ReadUserString(uint token);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/DotNet/ITokenResolver.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet {
4 | ///
5 | /// Resolves tokens
6 | ///
7 | public interface ITokenResolver {
8 | ///
9 | /// Resolves a token
10 | ///
11 | /// The metadata token
12 | /// Generic parameter context
13 | /// A or null if is invalid
14 | IMDTokenProvider ResolveToken(uint token, GenericParamContext gpContext);
15 | }
16 |
17 | public static partial class Extensions {
18 | ///
19 | /// Resolves a token
20 | ///
21 | /// This
22 | /// The metadata token
23 | /// A or null if is invalid
24 | public static IMDTokenProvider ResolveToken(this ITokenResolver self, uint token) => self.ResolveToken(token, new GenericParamContext());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/DotNet/IVariable.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet {
4 | ///
5 | /// Interface to access a local or a parameter
6 | ///
7 | public interface IVariable {
8 | ///
9 | /// Gets the variable type
10 | ///
11 | TypeSig Type { get; }
12 |
13 | ///
14 | /// Gets the 0-based position
15 | ///
16 | int Index { get; }
17 |
18 | ///
19 | /// Gets/sets the variable name
20 | ///
21 | string Name { get; set; }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/DotNet/MD/BlobStream.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using dnlib.IO;
5 |
6 | namespace dnlib.DotNet.MD {
7 | ///
8 | /// Represents the #Blob stream
9 | ///
10 | public sealed class BlobStream : HeapStream {
11 | ///
12 | public BlobStream() {
13 | }
14 |
15 | ///
16 | public BlobStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader)
17 | : base(mdReaderFactory, metadataBaseOffset, streamHeader) {
18 | }
19 |
20 | ///
21 | /// Reads data
22 | ///
23 | /// Offset of data
24 | /// The data or null if invalid offset
25 | public byte[] Read(uint offset) {
26 | // The CLR has a special check for offset 0. It always interprets it as
27 | // 0-length data, even if that first byte isn't 0 at all.
28 | if (offset == 0)
29 | return Array2.Empty();
30 | if (!TryCreateReader(offset, out var reader))
31 | return null;
32 | return reader.ToArray();
33 | }
34 |
35 | ///
36 | /// Reads data just like , but returns an empty array if
37 | /// offset is invalid
38 | ///
39 | /// Offset of data
40 | /// The data
41 | public byte[] ReadNoNull(uint offset) => Read(offset) ?? Array2.Empty();
42 |
43 | ///
44 | /// Creates a reader that can access a blob
45 | ///
46 | /// Offset of blob
47 | /// A new stream
48 | public DataReader CreateReader(uint offset) {
49 | if (TryCreateReader(offset, out var reader))
50 | return reader;
51 | return default;
52 | }
53 |
54 | ///
55 | /// Creates a reader that can access a blob or returns false on failure
56 | ///
57 | /// Offset of blob
58 | /// Updated with the reader
59 | ///
60 | public bool TryCreateReader(uint offset, out DataReader reader) {
61 | reader = dataReader;
62 | if (!IsValidOffset(offset))
63 | return false;
64 | reader.Position = offset;
65 | if (!reader.TryReadCompressedUInt32(out uint length))
66 | return false;
67 | if (!reader.CanRead(length))
68 | return false;
69 | reader = reader.Slice(reader.Position, length);
70 | return true;
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/DotNet/MD/ComImageFlags.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet.MD {
6 | ///
7 | /// See COMIMAGE_FLAGS_XXX in CorHdr.h in the Windows SDK
8 | ///
9 | [Flags]
10 | public enum ComImageFlags : uint {
11 | ///
12 | /// See COMIMAGE_FLAGS_ILONLY in the Windows SDK
13 | ///
14 | ILOnly = 1,
15 |
16 | ///
17 | /// See COMIMAGE_FLAGS_32BITREQUIRED in the Windows SDK
18 | ///
19 | Bit32Required = 2,
20 |
21 | ///
22 | /// Set if a native header exists (COMIMAGE_FLAGS_IL_LIBRARY)
23 | ///
24 | ILLibrary = 4,
25 |
26 | ///
27 | /// See COMIMAGE_FLAGS_STRONGNAMESIGNED in the Windows SDK
28 | ///
29 | StrongNameSigned = 8,
30 |
31 | ///
32 | /// See COMIMAGE_FLAGS_NATIVE_ENTRYPOINT in the Windows SDK
33 | ///
34 | NativeEntryPoint = 0x10,
35 |
36 | ///
37 | /// See COMIMAGE_FLAGS_TRACKDEBUGDATA in the Windows SDK
38 | ///
39 | TrackDebugData = 0x10000,
40 |
41 | ///
42 | /// See COMIMAGE_FLAGS_32BITPREFERRED in the Windows SDK
43 | ///
44 | Bit32Preferred = 0x20000,
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/DotNet/MD/CustomDotNetStream.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using dnlib.IO;
4 |
5 | namespace dnlib.DotNet.MD {
6 | ///
7 | /// A custom .NET metadata stream
8 | ///
9 | public class CustomDotNetStream : DotNetStream {
10 | ///
11 | /// Constructor
12 | ///
13 | public CustomDotNetStream() { }
14 |
15 | ///
16 | /// Constructor
17 | ///
18 | /// Data reader factory
19 | /// Offset of metadata
20 | /// The stream header
21 | public CustomDotNetStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader)
22 | : base(mdReaderFactory, metadataBaseOffset, streamHeader) {
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/DotNet/MD/GuidStream.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using dnlib.IO;
5 |
6 | namespace dnlib.DotNet.MD {
7 | ///
8 | /// Represents the #GUID stream
9 | ///
10 | public sealed class GuidStream : HeapStream {
11 | ///
12 | public GuidStream() {
13 | }
14 |
15 | ///
16 | public GuidStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader)
17 | : base(mdReaderFactory, metadataBaseOffset, streamHeader) {
18 | }
19 |
20 | ///
21 | public override bool IsValidIndex(uint index) => index == 0 || (index <= 0x10000000 && IsValidOffset((index - 1) * 16, 16));
22 |
23 | ///
24 | /// Read a
25 | ///
26 | /// Index into this stream
27 | /// A or null if is 0 or invalid
28 | public Guid? Read(uint index) {
29 | if (index == 0 || !IsValidIndex(index))
30 | return null;
31 | var reader = dataReader;
32 | reader.Position = (index - 1) * 16;
33 | return reader.ReadGuid();
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/DotNet/MD/HeapType.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.MD {
4 | ///
5 | /// Heap type. The values are set in stone by MS. Don't change.
6 | ///
7 | public enum HeapType : uint {
8 | /// #Strings heap
9 | Strings = 0,
10 | /// #GUID heap
11 | Guid = 1,
12 | /// #Blob heap
13 | Blob = 2,
14 | /// #US heap
15 | US = 3,
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/DotNet/MD/IRowReaders.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.MD {
4 | ///
5 | /// Reads metadata table columns
6 | ///
7 | public interface IColumnReader {
8 | ///
9 | /// Reads a column
10 | ///
11 | /// The table to read from
12 | /// Table row id
13 | /// The column to read
14 | /// Result
15 | /// true if was updated, false if
16 | /// the column should be read from the original table.
17 | bool ReadColumn(MDTable table, uint rid, ColumnInfo column, out uint value);
18 | }
19 |
20 | ///
21 | /// Reads table rows
22 | ///
23 | /// Raw row
24 | public interface IRowReader where TRow : struct {
25 | ///
26 | /// Reads a table row or returns false if the row should be read from the original table
27 | ///
28 | /// Row id
29 | /// The row
30 | ///
31 | bool TryReadRow(uint rid, out TRow row);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/DotNet/MD/MDHeaderRuntimeVersion.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.MD {
4 | ///
5 | /// Version strings found in the meta data header
6 | ///
7 | public static class MDHeaderRuntimeVersion {
8 | ///
9 | /// MS CLR 1.0 version string (.NET Framework 1.0)
10 | ///
11 | public const string MS_CLR_10 = "v1.0.3705";
12 |
13 | ///
14 | /// MS CLR 1.0 version string (.NET Framework 1.0). This is an incorrect version that shouldn't be used.
15 | ///
16 | public const string MS_CLR_10_X86RETAIL = "v1.x86ret";
17 |
18 | ///
19 | /// MS CLR 1.0 version string (.NET Framework 1.0). This is an incorrect version that shouldn't be used.
20 | ///
21 | public const string MS_CLR_10_RETAIL = "retail";
22 |
23 | ///
24 | /// MS CLR 1.0 version string (.NET Framework 1.0). This is an incorrect version that shouldn't be used.
25 | ///
26 | public const string MS_CLR_10_COMPLUS = "COMPLUS";
27 |
28 | ///
29 | /// MS CLR 1.1 version string (.NET Framework 1.1)
30 | ///
31 | public const string MS_CLR_11 = "v1.1.4322";
32 |
33 | ///
34 | /// MS CLR 2.0 version string (.NET Framework 2.0-3.5)
35 | ///
36 | public const string MS_CLR_20 = "v2.0.50727";
37 |
38 | ///
39 | /// MS CLR 4.0 version string (.NET Framework 4.0-4.5)
40 | ///
41 | public const string MS_CLR_40 = "v4.0.30319";
42 |
43 | ///
44 | /// MS CLR 1.0 any version
45 | ///
46 | public const string MS_CLR_10_PREFIX = "v1.0";
47 |
48 | ///
49 | /// MS CLR 1.0 any version
50 | ///
51 | public const string MS_CLR_10_PREFIX_X86RETAIL = "v1.x86";
52 |
53 | ///
54 | /// MS CLR 1.1 any version
55 | ///
56 | public const string MS_CLR_11_PREFIX = "v1.1";
57 |
58 | ///
59 | /// MS CLR 2.0 any version
60 | ///
61 | public const string MS_CLR_20_PREFIX = "v2.0";
62 |
63 | ///
64 | /// MS CLR 4.0 any version
65 | ///
66 | public const string MS_CLR_40_PREFIX = "v4.0";
67 |
68 | ///
69 | /// ECMA 2002 version string
70 | ///
71 | public const string ECMA_2002 = "Standard CLI 2002";
72 |
73 | ///
74 | /// ECMA 2005 version string
75 | ///
76 | public const string ECMA_2005 = "Standard CLI 2005";
77 |
78 | ///
79 | /// Portable PDB v1.0
80 | ///
81 | public const string PORTABLE_PDB_V1_0 = "PDB v1.0";
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/DotNet/MD/MDStreamFlags.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet.MD {
6 | ///
7 | /// MDStream flags
8 | ///
9 | [Flags]
10 | public enum MDStreamFlags : byte {
11 | /// #Strings stream is big and requires 4 byte offsets
12 | BigStrings = 1,
13 | /// #GUID stream is big and requires 4 byte offsets
14 | BigGUID = 2,
15 | /// #Blob stream is big and requires 4 byte offsets
16 | BigBlob = 4,
17 | ///
18 | Padding = 8,
19 | ///
20 | DeltaOnly = 0x20,
21 | /// Extra data follows the row counts
22 | ExtraData = 0x40,
23 | /// Set if certain tables can contain deleted rows. The name column (if present) is set to "_Deleted"
24 | HasDelete = 0x80,
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/DotNet/MD/PdbStream.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using dnlib.IO;
4 |
5 | namespace dnlib.DotNet.MD {
6 | ///
7 | /// #Pdb stream
8 | ///
9 | public sealed class PdbStream : HeapStream {
10 | ///
11 | /// Gets the PDB id
12 | ///
13 | public byte[] Id { get; private set; }
14 |
15 | ///
16 | /// Gets the entry point token or 0
17 | ///
18 | public MDToken EntryPoint { get; private set; }
19 |
20 | ///
21 | /// Gets the referenced type system tables in the PE metadata file
22 | ///
23 | public ulong ReferencedTypeSystemTables { get; private set; }
24 |
25 | ///
26 | /// Gets all type system table rows. This array has exactly 64 elements.
27 | ///
28 | public uint[] TypeSystemTableRows { get; private set; }
29 |
30 | ///
31 | public PdbStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader)
32 | : base(mdReaderFactory, metadataBaseOffset, streamHeader) {
33 | var reader = CreateReader();
34 | Id = reader.ReadBytes(20);
35 | EntryPoint = new MDToken(reader.ReadUInt32());
36 | var tables = reader.ReadUInt64();
37 | ReferencedTypeSystemTables = tables;
38 | var rows = new uint[64];
39 | for (int i = 0; i < rows.Length; i++, tables >>= 1) {
40 | if (((uint)tables & 1) != 0)
41 | rows[i] = reader.ReadUInt32();
42 | }
43 | TypeSystemTableRows = rows;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/DotNet/MD/StorageFlags.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet.MD {
6 | ///
7 | /// Storage flags found in the MD header
8 | ///
9 | [Flags]
10 | public enum StorageFlags : byte {
11 | ///
12 | /// Normal flags
13 | ///
14 | Normal = 0,
15 |
16 | ///
17 | /// More data after the header but before the streams.
18 | ///
19 | /// The CLR will fail to load the file if this flag (or any other bits) is set.
20 | ExtraData = 1,
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/DotNet/MD/StringsStream.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using dnlib.IO;
4 |
5 | namespace dnlib.DotNet.MD {
6 | ///
7 | /// Represents the #Strings stream
8 | ///
9 | public sealed class StringsStream : HeapStream {
10 | ///
11 | public StringsStream() {
12 | }
13 |
14 | ///
15 | public StringsStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader)
16 | : base(mdReaderFactory, metadataBaseOffset, streamHeader) {
17 | }
18 |
19 | ///
20 | /// Reads a
21 | ///
22 | /// Offset of string
23 | /// A instance or null if invalid offset
24 | public UTF8String Read(uint offset) {
25 | if (offset >= StreamLength)
26 | return null;
27 | byte[] data;
28 | var reader = dataReader;
29 | reader.Position = offset;
30 | data = reader.TryReadBytesUntil(0);
31 | if (data is null)
32 | return null;
33 | return new UTF8String(data);
34 | }
35 |
36 | ///
37 | /// Reads a . The empty string is returned if
38 | /// is invalid.
39 | ///
40 | /// Offset of string
41 | /// A instance
42 | public UTF8String ReadNoNull(uint offset) => Read(offset) ?? UTF8String.Empty;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/DotNet/MD/TableInfo.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Diagnostics;
4 |
5 | namespace dnlib.DotNet.MD {
6 | ///
7 | /// Info about one MD table
8 | ///
9 | [DebuggerDisplay("{rowSize} {name}")]
10 | public sealed class TableInfo {
11 | readonly Table table;
12 | int rowSize;
13 | readonly ColumnInfo[] columns;
14 | readonly string name;
15 |
16 | ///
17 | /// Returns the table type
18 | ///
19 | public Table Table => table;
20 |
21 | ///
22 | /// Returns the total size of a row in bytes
23 | ///
24 | public int RowSize {
25 | get => rowSize;
26 | internal set => rowSize = value;
27 | }
28 |
29 | ///
30 | /// Returns all the columns
31 | ///
32 | public ColumnInfo[] Columns => columns;
33 |
34 | ///
35 | /// Returns the name of the table
36 | ///
37 | public string Name => name;
38 |
39 | ///
40 | /// Constructor
41 | ///
42 | /// Table type
43 | /// Table name
44 | /// All columns
45 | public TableInfo(Table table, string name, ColumnInfo[] columns) {
46 | this.table = table;
47 | this.name = name;
48 | this.columns = columns;
49 | }
50 |
51 | ///
52 | /// Constructor
53 | ///
54 | /// Table type
55 | /// Table name
56 | /// All columns
57 | /// Row size
58 | public TableInfo(Table table, string name, ColumnInfo[] columns, int rowSize) {
59 | this.table = table;
60 | this.name = name;
61 | this.columns = columns;
62 | this.rowSize = rowSize;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/DotNet/MD/USStream.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using dnlib.IO;
5 |
6 | namespace dnlib.DotNet.MD {
7 | ///
8 | /// Represents the #US stream
9 | ///
10 | public sealed class USStream : HeapStream {
11 | ///
12 | public USStream() {
13 | }
14 |
15 | ///
16 | public USStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader)
17 | : base(mdReaderFactory, metadataBaseOffset, streamHeader) {
18 | }
19 |
20 | ///
21 | /// Reads a unicode string
22 | ///
23 | /// Offset of unicode string
24 | /// A string or null if is invalid
25 | public string Read(uint offset) {
26 | if (offset == 0)
27 | return string.Empty;
28 | if (!IsValidOffset(offset))
29 | return null;
30 | var reader = dataReader;
31 | reader.Position = offset;
32 | if (!reader.TryReadCompressedUInt32(out uint length))
33 | return null;
34 | if (!reader.CanRead(length))
35 | return null;
36 | try {
37 | return reader.ReadUtf16String((int)(length / 2));
38 | }
39 | catch (OutOfMemoryException) {
40 | throw;
41 | }
42 | catch {
43 | // It's possible that an exception is thrown when converting a char* to
44 | // a string. If so, return an empty string.
45 | return string.Empty;
46 | }
47 | }
48 |
49 | ///
50 | /// Reads data just like , but returns an empty string if
51 | /// offset is invalid
52 | ///
53 | /// Offset of unicode string
54 | /// The string
55 | public string ReadNoNull(uint offset) => Read(offset) ?? string.Empty;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/DotNet/ManifestResourceAttributes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// ManifestResource flags. See CorHdr.h/CorManifestResourceFlags
8 | ///
9 | [Flags]
10 | public enum ManifestResourceAttributes : uint {
11 | ///
12 | VisibilityMask = 0x0007,
13 | /// The Resource is exported from the Assembly.
14 | Public = 0x0001,
15 | /// The Resource is private to the Assembly.
16 | Private = 0x0002,
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/DotNet/MemberMDInitializer.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Collections.Generic;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Methods to load properties to make sure they're initialized
8 | ///
9 | static class MemberMDInitializer {
10 | ///
11 | /// Read every collection element
12 | ///
13 | /// Collection element type
14 | /// Collection
15 | public static void Initialize(IEnumerable coll) {
16 | if (coll is null)
17 | return;
18 | foreach (var c in coll) {
19 | }
20 | }
21 |
22 | ///
23 | /// Load the object instance
24 | ///
25 | /// The value (ignored)
26 | public static void Initialize(object o) {
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/DotNet/MethodAttributes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Method attributes, see CorHdr.h/CorMethodAttr
8 | ///
9 | [Flags]
10 | public enum MethodAttributes : ushort {
11 | /// member access mask - Use this mask to retrieve accessibility information.
12 | MemberAccessMask = 0x0007,
13 | /// Member not referenceable.
14 | PrivateScope = 0x0000,
15 | /// Member not referenceable.
16 | CompilerControlled = PrivateScope,
17 | /// Accessible only by the parent type.
18 | Private = 0x0001,
19 | /// Accessible by sub-types only in this Assembly.
20 | FamANDAssem = 0x0002,
21 | /// Accessibly by anyone in the Assembly.
22 | Assembly = 0x0003,
23 | /// Accessible only by type and sub-types.
24 | Family = 0x0004,
25 | /// Accessibly by sub-types anywhere, plus anyone in assembly.
26 | FamORAssem = 0x0005,
27 | /// Accessibly by anyone who has visibility to this scope.
28 | Public = 0x0006,
29 |
30 | /// Defined on type, else per instance.
31 | Static = 0x0010,
32 | /// Method may not be overridden.
33 | Final = 0x0020,
34 | /// Method virtual.
35 | Virtual = 0x0040,
36 | /// Method hides by name+sig, else just by name.
37 | HideBySig = 0x0080,
38 |
39 | /// vtable layout mask - Use this mask to retrieve vtable attributes.
40 | VtableLayoutMask = 0x0100,
41 | /// The default.
42 | ReuseSlot = 0x0000,
43 | /// Method always gets a new slot in the vtable.
44 | NewSlot = 0x0100,
45 |
46 | /// Overridability is the same as the visibility.
47 | CheckAccessOnOverride = 0x0200,
48 | /// Method does not provide an implementation.
49 | Abstract = 0x0400,
50 | /// Method is special. Name describes how.
51 | SpecialName = 0x0800,
52 |
53 | /// Implementation is forwarded through pinvoke.
54 | PinvokeImpl = 0x2000,
55 | /// Managed method exported via thunk to unmanaged code.
56 | UnmanagedExport = 0x0008,
57 |
58 | /// Runtime should check name encoding.
59 | RTSpecialName = 0x1000,
60 | /// Method has security associate with it.
61 | HasSecurity = 0x4000,
62 | /// Method calls another method containing security code.
63 | RequireSecObject = 0x8000,
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/DotNet/MethodImplAttributes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Method impl attributes, see CorHdr.h/CorMethodImpl
8 | ///
9 | [Flags]
10 | public enum MethodImplAttributes : ushort {
11 | /// Flags about code type.
12 | CodeTypeMask = 0x0003,
13 | /// Method impl is IL.
14 | IL = 0x0000,
15 | /// Method impl is native.
16 | Native = 0x0001,
17 | /// Method impl is OPTIL
18 | OPTIL = 0x0002,
19 | /// Method impl is provided by the runtime.
20 | Runtime = 0x0003,
21 |
22 | /// Flags specifying whether the code is managed or unmanaged.
23 | ManagedMask = 0x0004,
24 | /// Method impl is unmanaged, otherwise managed.
25 | Unmanaged = 0x0004,
26 | /// Method impl is managed.
27 | Managed = 0x0000,
28 |
29 | /// Indicates method is defined; used primarily in merge scenarios.
30 | ForwardRef = 0x0010,
31 | /// Indicates method sig is not to be mangled to do HRESULT conversion.
32 | PreserveSig = 0x0080,
33 |
34 | /// Reserved for internal use.
35 | InternalCall = 0x1000,
36 |
37 | /// Method is single threaded through the body.
38 | Synchronized = 0x0020,
39 | /// Method may not be inlined.
40 | NoInlining = 0x0008,
41 | /// Method should be inlined if possible.
42 | AggressiveInlining = 0x0100,
43 | /// Method may not be optimized.
44 | NoOptimization = 0x0040,
45 | /// Method may contain hot code and should be aggressively optimized.
46 | AggressiveOptimization = 0x0200,
47 | /// The JIT compiler should look for security mitigation attributes, such as the user-defined System.Runtime.CompilerServices.SecurityMitigationsAttribute. If found, the JIT compiler applies any related security mitigations. Available starting with .NET Framework 4.8.
48 | SecurityMitigations = 0x0400,
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/DotNet/MethodOverride.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet {
4 | ///
5 | /// Describes which method some method implements
6 | ///
7 | public struct MethodOverride {
8 | ///
9 | /// The method body. Usually a but could be a
10 | ///
11 | public IMethodDefOrRef MethodBody;
12 |
13 | ///
14 | /// The method implements
15 | ///
16 | public IMethodDefOrRef MethodDeclaration;
17 |
18 | ///
19 | /// Constructor
20 | ///
21 | /// Method body
22 | /// The method implements
23 | public MethodOverride(IMethodDefOrRef methodBody, IMethodDefOrRef methodDeclaration) {
24 | MethodBody = methodBody;
25 | MethodDeclaration = methodDeclaration;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/DotNet/MethodSemanticsAttributes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Method semantics flags, see CorHdr.h/CorMethodSemanticsAttr
8 | ///
9 | [Flags]
10 | public enum MethodSemanticsAttributes : ushort {
11 | /// No bit is set
12 | None = 0,
13 | /// Setter for property
14 | Setter = 0x0001,
15 | /// Getter for property
16 | Getter = 0x0002,
17 | /// other method for property or event
18 | Other = 0x0004,
19 | /// AddOn method for event
20 | AddOn = 0x0008,
21 | /// RemoveOn method for event
22 | RemoveOn = 0x0010,
23 | /// Fire method for event
24 | Fire = 0x0020,
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/DotNet/ModuleKind.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet {
4 | ///
5 | /// Module kind
6 | ///
7 | public enum ModuleKind {
8 | ///
9 | /// Console UI module
10 | ///
11 | Console,
12 |
13 | ///
14 | /// Windows GUI module
15 | ///
16 | Windows,
17 |
18 | ///
19 | /// DLL module
20 | ///
21 | Dll,
22 |
23 | ///
24 | /// Netmodule (it has no assembly manifest)
25 | ///
26 | NetModule,
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/DotNet/NullResolver.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet {
4 | ///
5 | /// A resolver that always fails
6 | ///
7 | public sealed class NullResolver : IAssemblyResolver, IResolver {
8 | ///
9 | /// The one and only instance of this type
10 | ///
11 | public static readonly NullResolver Instance = new NullResolver();
12 |
13 | NullResolver() {
14 | }
15 |
16 | ///
17 | public AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule) => null;
18 |
19 | ///
20 | public TypeDef Resolve(TypeRef typeRef, ModuleDef sourceModule) => null;
21 |
22 | ///
23 | public IMemberForwarded Resolve(MemberRef memberRef) => null;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/DotNet/PInvokeAttributes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// P/Invoke attributes, see CorHdr.h/CorPinvokeMap
8 | ///
9 | [Flags]
10 | public enum PInvokeAttributes : ushort {
11 | /// Pinvoke is to use the member name as specified.
12 | NoMangle = 0x0001,
13 |
14 | /// Use this mask to retrieve the CharSet information.
15 | CharSetMask = 0x0006,
16 | ///
17 | CharSetNotSpec = 0x0000,
18 | ///
19 | CharSetAnsi = 0x0002,
20 | ///
21 | CharSetUnicode = 0x0004,
22 | ///
23 | CharSetAuto = 0x0006,
24 |
25 | ///
26 | BestFitUseAssem = 0x0000,
27 | ///
28 | BestFitEnabled = 0x0010,
29 | ///
30 | BestFitDisabled = 0x0020,
31 | ///
32 | BestFitMask = 0x0030,
33 |
34 | ///
35 | ThrowOnUnmappableCharUseAssem = 0x0000,
36 | ///
37 | ThrowOnUnmappableCharEnabled = 0x1000,
38 | ///
39 | ThrowOnUnmappableCharDisabled = 0x2000,
40 | ///
41 | ThrowOnUnmappableCharMask = 0x3000,
42 |
43 | /// Information about target function. Not relevant for fields.
44 | SupportsLastError = 0x0040,
45 |
46 | ///
47 | CallConvMask = 0x0700,
48 | /// Pinvoke will use native callconv appropriate to target windows platform.
49 | CallConvWinapi = 0x0100,
50 | ///
51 | CallConvCdecl = 0x0200,
52 | ///
53 | CallConvStdcall = 0x0300,
54 | ///
55 | CallConvStdCall = CallConvStdcall,
56 | /// In M9, pinvoke will raise exception.
57 | CallConvThiscall = 0x0400,
58 | ///
59 | CallConvFastcall = 0x0500,
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/DotNet/ParamAttributes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Parameter flags. See CorHdr.h/CorParamAttr
8 | ///
9 | [Flags]
10 | public enum ParamAttributes : ushort {
11 | /// Param is [In]
12 | In = 0x0001,
13 | /// Param is [out]
14 | Out = 0x0002,
15 | /// Param is a locale identifier
16 | Lcid = 0x0004,
17 | /// Param is a return value
18 | Retval = 0x0008,
19 | /// Param is optional
20 | Optional = 0x0010,
21 |
22 | /// Param has default value.
23 | HasDefault = 0x1000,
24 | /// Param has FieldMarshal.
25 | HasFieldMarshal = 0x2000,
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/CustomDebugInfoGuids.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet.Pdb {
6 | ///
7 | /// Custom debug info guids
8 | ///
9 | public static class CustomDebugInfoGuids {
10 | #pragma warning disable 1591 // Missing XML comment for publicly visible type or member
11 | // Roslyn: PortableCustomDebugInfoKinds.cs
12 | public static readonly Guid AsyncMethodSteppingInformationBlob = new Guid("54FD2AC5-E925-401A-9C2A-F94F171072F8");
13 | public static readonly Guid DefaultNamespace = new Guid("58B2EAB6-209F-4E4E-A22C-B2D0F910C782");
14 | public static readonly Guid DynamicLocalVariables = new Guid("83C563C4-B4F3-47D5-B824-BA5441477EA8");
15 | public static readonly Guid EmbeddedSource = new Guid("0E8A571B-6926-466E-B4AD-8AB04611F5FE");
16 | public static readonly Guid EncLambdaAndClosureMap = new Guid("A643004C-0240-496F-A783-30D64F4979DE");
17 | public static readonly Guid EncLocalSlotMap = new Guid("755F52A8-91C5-45BE-B4B8-209571E552BD");
18 | public static readonly Guid SourceLink = new Guid("CC110556-A091-4D38-9FEC-25AB9A351A6A");
19 | public static readonly Guid StateMachineHoistedLocalScopes = new Guid("6DA9A61E-F8C7-4874-BE62-68BC5630DF71");
20 | public static readonly Guid TupleElementNames = new Guid("ED9FDF71-8879-4747-8ED3-FE5EDE3CE710");
21 | public static readonly Guid CompilationMetadataReferences = new Guid("7E4D4708-096E-4C5C-AEDA-CB10BA6A740D");
22 | public static readonly Guid CompilationOptions = new Guid("B5FEEC05-8CD0-4A83-96DA-466284BB4BD8");
23 | public static readonly Guid TypeDefinitionDocuments = new Guid("932E74BC-DBA9-4478-8D46-0F32A7BAB3D3");
24 | public static readonly Guid EncStateMachineStateMap = new Guid("8B78CD68-2EDE-420B-980B-E15884B8AAA3");
25 | public static readonly Guid PrimaryConstructorInformationBlob = new Guid("9D40ACE1-C703-4D0E-BF41-7243060A8FB5");
26 | #pragma warning restore 1591 // Missing XML comment for publicly visible type or member
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/DataReaderFactoryUtils.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.IO;
5 | using System.Security;
6 | using dnlib.IO;
7 |
8 | namespace dnlib.DotNet.Pdb {
9 | static class DataReaderFactoryUtils {
10 | public static DataReaderFactory TryCreateDataReaderFactory(string filename) {
11 | try {
12 | if (!File.Exists(filename))
13 | return null;
14 | // Don't use memory mapped I/O
15 | return ByteArrayDataReaderFactory.Create(File.ReadAllBytes(filename), filename);
16 | }
17 | catch (IOException) {
18 | }
19 | catch (UnauthorizedAccessException) {
20 | }
21 | catch (SecurityException) {
22 | }
23 | return null;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Dss/SymbolDocumentWriter.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Diagnostics.SymbolStore;
5 |
6 | namespace dnlib.DotNet.Pdb.Dss {
7 | sealed class SymbolDocumentWriter : ISymbolDocumentWriter {
8 | readonly ISymUnmanagedDocumentWriter writer;
9 | public ISymUnmanagedDocumentWriter SymUnmanagedDocumentWriter => writer;
10 | public SymbolDocumentWriter(ISymUnmanagedDocumentWriter writer) => this.writer = writer;
11 | public void SetCheckSum(Guid algorithmId, byte[] checkSum) {
12 | if (checkSum is not null && checkSum.Length != 0 && algorithmId != Guid.Empty)
13 | writer.SetCheckSum(algorithmId, (uint)checkSum.Length, checkSum);
14 | }
15 | public void SetSource(byte[] source) => writer.SetSource((uint)source.Length, source);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Dss/SymbolNamespaceImpl.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using dnlib.DotNet.Pdb.Symbols;
4 |
5 | namespace dnlib.DotNet.Pdb.Dss {
6 | sealed class SymbolNamespaceImpl : SymbolNamespace {
7 | readonly ISymUnmanagedNamespace ns;
8 |
9 | public SymbolNamespaceImpl(ISymUnmanagedNamespace @namespace) => ns = @namespace;
10 |
11 | public override string Name {
12 | get {
13 | ns.GetName(0, out uint count, null);
14 | var chars = new char[count];
15 | ns.GetName((uint)chars.Length, out count, chars);
16 | if (chars.Length == 0)
17 | return string.Empty;
18 | return new string(chars, 0, chars.Length - 1);
19 | }
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Dss/SymbolVariableImpl.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using dnlib.DotNet.Pdb.Symbols;
5 | using dnlib.DotNet.Pdb.WindowsPdb;
6 |
7 | namespace dnlib.DotNet.Pdb.Dss {
8 | sealed class SymbolVariableImpl : SymbolVariable {
9 | readonly ISymUnmanagedVariable variable;
10 |
11 | public SymbolVariableImpl(ISymUnmanagedVariable variable) => this.variable = variable;
12 |
13 | public override int Index {
14 | get {
15 | variable.GetAddressField1(out uint result);
16 | return (int)result;
17 | }
18 | }
19 |
20 | public override PdbLocalAttributes Attributes {
21 | get {
22 | variable.GetAttributes(out uint result);
23 | if ((result & (uint)CorSymVarFlag.VAR_IS_COMP_GEN) != 0)
24 | return PdbLocalAttributes.DebuggerHidden;
25 | return PdbLocalAttributes.None;
26 | }
27 | }
28 |
29 | public override string Name {
30 | get {
31 | variable.GetName(0, out uint count, null);
32 | var chars = new char[count];
33 | variable.GetName((uint)chars.Length, out count, chars);
34 | if (chars.Length == 0)
35 | return string.Empty;
36 | return new string(chars, 0, chars.Length - 1);
37 | }
38 | }
39 |
40 | public override PdbCustomDebugInfo[] CustomDebugInfos => Array2.Empty();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/IMAGE_DEBUG_DIRECTORY.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using dnlib.PE;
4 |
5 | namespace dnlib.DotNet.Pdb {
6 | ///
7 | /// IMAGE_DEBUG_DIRECTORY
8 | ///
9 | public struct IMAGE_DEBUG_DIRECTORY {
10 | #pragma warning disable 1591
11 | public uint Characteristics;
12 | public uint TimeDateStamp;
13 | public ushort MajorVersion;
14 | public ushort MinorVersion;
15 | public ImageDebugType Type;
16 | public uint SizeOfData;
17 | public uint AddressOfRawData;
18 | public uint PointerToRawData;
19 | #pragma warning restore 1591
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Managed/DbiDocument.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Diagnostics;
5 | using System.Diagnostics.SymbolStore;
6 | using dnlib.DotNet.Pdb.Symbols;
7 | using dnlib.IO;
8 |
9 | namespace dnlib.DotNet.Pdb.Managed {
10 | sealed class DbiDocument : SymbolDocument {
11 | readonly string url;
12 | Guid language;
13 | Guid languageVendor;
14 | Guid documentType;
15 | Guid checkSumAlgorithmId;
16 | byte[] checkSum;
17 | byte[] sourceCode;
18 |
19 | public override string URL => url;
20 | public override Guid Language => language;
21 | public override Guid LanguageVendor => languageVendor;
22 | public override Guid DocumentType => documentType;
23 | public override Guid CheckSumAlgorithmId => checkSumAlgorithmId;
24 | public override byte[] CheckSum => checkSum;
25 | byte[] SourceCode => sourceCode;
26 |
27 | public override PdbCustomDebugInfo[] CustomDebugInfos {
28 | get {
29 | if (customDebugInfos is null) {
30 | var sourceCode = SourceCode;
31 | if (sourceCode is not null)
32 | customDebugInfos = new PdbCustomDebugInfo[1] { new PdbEmbeddedSourceCustomDebugInfo(sourceCode) };
33 | else
34 | customDebugInfos = Array2.Empty();
35 | }
36 | return customDebugInfos;
37 | }
38 | }
39 | PdbCustomDebugInfo[] customDebugInfos;
40 |
41 | public override MDToken? MDToken => null;
42 |
43 | public DbiDocument(string url) {
44 | this.url = url;
45 | documentType = SymDocumentType.Text;
46 | }
47 |
48 | public void Read(ref DataReader reader) {
49 | reader.Position = 0;
50 | language = reader.ReadGuid();
51 | languageVendor = reader.ReadGuid();
52 | documentType = reader.ReadGuid();
53 | checkSumAlgorithmId = reader.ReadGuid();
54 | int checkSumLen = reader.ReadInt32();
55 | int sourceLen = reader.ReadInt32();
56 | checkSum = reader.ReadBytes(checkSumLen);
57 | sourceCode = sourceLen == 0 ? null : reader.ReadBytes(sourceLen);
58 | Debug.Assert(reader.BytesLeft == 0);
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Managed/DbiNamespace.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using dnlib.DotNet.Pdb.Symbols;
4 |
5 | namespace dnlib.DotNet.Pdb.Managed {
6 | sealed class DbiNamespace : SymbolNamespace {
7 | public override string Name => name;
8 | readonly string name;
9 |
10 | public DbiNamespace(string ns) => name = ns;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Managed/DbiVariable.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using dnlib.DotNet.Pdb.Symbols;
5 | using dnlib.IO;
6 |
7 | namespace dnlib.DotNet.Pdb.Managed {
8 | sealed class DbiVariable : SymbolVariable {
9 | public override string Name => name;
10 | string name;
11 |
12 | public override PdbLocalAttributes Attributes => attributes;
13 | PdbLocalAttributes attributes;
14 |
15 | public override int Index => index;
16 | int index;
17 |
18 | public override PdbCustomDebugInfo[] CustomDebugInfos => Array2.Empty();
19 |
20 | public bool Read(ref DataReader reader) {
21 | index = reader.ReadInt32();
22 | reader.Position += 10;
23 | ushort flags = reader.ReadUInt16();
24 | attributes = GetAttributes(flags);
25 | name = PdbReader.ReadCString(ref reader);
26 |
27 | const int fIsParam = 1;
28 | return (flags & fIsParam) == 0;
29 | }
30 |
31 | static PdbLocalAttributes GetAttributes(uint flags) {
32 | PdbLocalAttributes res = 0;
33 | const int fCompGenx = 4;
34 | if ((flags & fCompGenx) != 0)
35 | res |= PdbLocalAttributes.DebuggerHidden;
36 | return res;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Managed/ModuleStreamType.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Pdb.Managed {
4 | enum ModuleStreamType : uint {
5 | Symbols = 0xF1,
6 | Lines = 0xF2,
7 | StringTable = 0xF3,
8 | FileInfo = 0xF4,
9 | FrameData = 0xF5,
10 | InlineeLines = 0xF6,
11 | CrossScopeImports = 0xF7,
12 | CrossScopeExports = 0xF8,
13 | ILLines = 0xF9,
14 | FuncMDTokenMap = 0xFA,
15 | TypeMDTokenMap = 0xFB,
16 | MergedAssemblyInput = 0xFC,
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Managed/MsfStream.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using dnlib.IO;
5 |
6 | namespace dnlib.DotNet.Pdb.Managed {
7 | sealed class MsfStream {
8 | public MsfStream(DataReader[] pages, uint length) {
9 | var buf = new byte[length];
10 | int offset = 0;
11 | for (int i = 0; i < pages.Length; i++) {
12 | var page = pages[i];
13 | page.Position = 0;
14 | int len = Math.Min((int)page.Length, (int)(length - offset));
15 | page.ReadBytes(buf, offset, len);
16 | offset += len;
17 | }
18 | Content = ByteArrayDataReaderFactory.CreateReader(buf);
19 | }
20 |
21 | public DataReader Content;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Managed/NumericLeaf.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Pdb.Managed {
4 | enum NumericLeaf : ushort {
5 | LF_NUMERIC = 0x8000,
6 | LF_CHAR = 0x8000,
7 | LF_SHORT = 0x8001,
8 | LF_USHORT = 0x8002,
9 | LF_LONG = 0x8003,
10 | LF_ULONG = 0x8004,
11 | LF_REAL32 = 0x8005,
12 | LF_REAL64 = 0x8006,
13 | LF_REAL80 = 0x8007,
14 | LF_REAL128 = 0x8008,
15 | LF_QUADWORD = 0x8009,
16 | LF_UQUADWORD = 0x800A,
17 | LF_REAL48 = 0x800B,
18 | LF_COMPLEX32 = 0x800C,
19 | LF_COMPLEX64 = 0x800D,
20 | LF_COMPLEX80 = 0x800E,
21 | LF_COMPLEX128 = 0x800F,
22 | LF_VARSTRING = 0x8010,
23 | LF_RESERVED_8011 = 0x8011,
24 | LF_RESERVED_8012 = 0x8012,
25 | LF_RESERVED_8013 = 0x8013,
26 | LF_RESERVED_8014 = 0x8014,
27 | LF_RESERVED_8015 = 0x8015,
28 | LF_RESERVED_8016 = 0x8016,
29 | LF_OCTWORD = 0x8017,
30 | LF_UOCTWORD = 0x8018,
31 | LF_VARIANT = 0x8019,
32 | LF_DATE = 0x801A,
33 | LF_UTF8STRING = 0x801B,
34 | LF_REAL16 = 0x801C,
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Managed/PdbException.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Runtime.Serialization;
5 |
6 | namespace dnlib.DotNet.Pdb.Managed {
7 | ///
8 | /// Exception that is thrown when encounters an error.
9 | ///
10 | [Serializable]
11 | sealed class PdbException : Exception {
12 | ///
13 | /// Constructor
14 | ///
15 | public PdbException() {
16 | }
17 |
18 | ///
19 | /// Constructor
20 | ///
21 | /// Exception message
22 | public PdbException(string message)
23 | : base($"Failed to read PDB: {message}") {
24 | }
25 |
26 | ///
27 | /// Constructor
28 | ///
29 | /// Inner exception
30 | public PdbException(Exception innerException)
31 | : base($"Failed to read PDB: {innerException.Message}", innerException) {
32 | }
33 |
34 | ///
35 | /// Constructor
36 | ///
37 | ///
38 | ///
39 | public PdbException(SerializationInfo info, StreamingContext context)
40 | : base(info, context) {
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Managed/SymbolReaderFactory.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.IO;
4 | using dnlib.DotNet.Pdb.Symbols;
5 | using dnlib.IO;
6 |
7 | namespace dnlib.DotNet.Pdb.Managed {
8 | ///
9 | /// Creates a instance
10 | ///
11 | static class SymbolReaderFactory {
12 | ///
13 | /// Creates a new instance
14 | ///
15 | /// PDB context
16 | /// PDB file stream which is now owned by this method
17 | /// A new instance or null.
18 | public static SymbolReader Create(PdbReaderContext pdbContext, DataReaderFactory pdbStream) {
19 | if (pdbStream is null)
20 | return null;
21 | try {
22 | var debugDir = pdbContext.CodeViewDebugDirectory;
23 | if (debugDir is null)
24 | return null;
25 | if (!pdbContext.TryGetCodeViewData(out var pdbGuid, out uint age))
26 | return null;
27 |
28 | var pdbReader = new PdbReader(pdbGuid, age);
29 | pdbReader.Read(pdbStream.CreateReader());
30 | if (pdbReader.MatchesModule)
31 | return pdbReader;
32 | return null;
33 | }
34 | catch (PdbException) {
35 | }
36 | catch (IOException) {
37 | }
38 | finally {
39 | pdbStream?.Dispose();
40 | }
41 | return null;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/PdbConstant.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Collections.Generic;
4 |
5 | namespace dnlib.DotNet.Pdb {
6 | ///
7 | /// A constant in a method scope, eg. "const int SomeConstant = 123;"
8 | ///
9 | public sealed class PdbConstant : IHasCustomDebugInformation {
10 | string name;
11 | TypeSig type;
12 | object value;
13 |
14 | ///
15 | /// Gets/sets the name
16 | ///
17 | public string Name {
18 | get => name;
19 | set => name = value;
20 | }
21 |
22 | ///
23 | /// Gets/sets the type of the constant
24 | ///
25 | public TypeSig Type {
26 | get => type;
27 | set => type = value;
28 | }
29 |
30 | ///
31 | /// Gets/sets the value of the constant
32 | ///
33 | public object Value {
34 | get => value;
35 | set => this.value = value;
36 | }
37 |
38 | ///
39 | /// Constructor
40 | ///
41 | public PdbConstant() {
42 | }
43 |
44 | ///
45 | /// Constructor
46 | ///
47 | /// Name of constant
48 | /// Type of constant
49 | /// Constant value
50 | public PdbConstant(string name, TypeSig type, object value) {
51 | this.name = name;
52 | this.type = type;
53 | this.value = value;
54 | }
55 |
56 | ///
57 | public int HasCustomDebugInformationTag => 25;
58 |
59 | ///
60 | public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0;
61 |
62 | ///
63 | /// Gets all custom debug infos
64 | ///
65 | public IList CustomDebugInfos => customDebugInfos;
66 | readonly IList customDebugInfos = new List();
67 |
68 | ///
69 | /// ToString()
70 | ///
71 | ///
72 | public override string ToString() {
73 | var type = Type;
74 | var value = Value;
75 | string typeString = type is null ? "" : type.ToString();
76 | string valueString = value is null ? "null" : $"{value} ({value.GetType().FullName})";
77 | return$"{typeString} {Name} = {valueString}";
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/PdbDocumentConstants.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet.Pdb {
6 | ///
7 | /// PDB document constants
8 | ///
9 | public static class PdbDocumentConstants {
10 | #pragma warning disable 1591 // Missing XML comment for publicly visible type or member
11 | public static readonly Guid LanguageCSharp = new Guid("3F5162F8-07C6-11D3-9053-00C04FA302A1");
12 | public static readonly Guid LanguageVisualBasic = new Guid("3A12D0B8-C26C-11D0-B442-00A0244A1DD2");
13 | public static readonly Guid LanguageFSharp = new Guid("AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3");
14 |
15 | public static readonly Guid HashSHA1 = new Guid("FF1816EC-AA5E-4D10-87F7-6F4963833460");
16 | public static readonly Guid HashSHA256 = new Guid("8829D00F-11B8-4213-878B-770E8597AC16");
17 |
18 | public static readonly Guid LanguageVendorMicrosoft = new Guid("994B45C4-E6E9-11D2-903F-00C04FA302A1");
19 |
20 | public static readonly Guid DocumentTypeText = new Guid("5A869D0B-6611-11D3-BD2A-0000F80849BD");
21 | #pragma warning restore 1591 // Missing XML comment for publicly visible type or member
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/PdbFileKind.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Pdb {
4 | ///
5 | /// PDB file kind
6 | ///
7 | public enum PdbFileKind {
8 | ///
9 | /// Windows PDB
10 | ///
11 | WindowsPDB,
12 |
13 | ///
14 | /// Portable PDB
15 | ///
16 | PortablePDB,
17 |
18 | ///
19 | /// Embedded portable PDB
20 | ///
21 | EmbeddedPortablePDB,
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/PdbLocal.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Collections.Generic;
4 | using dnlib.DotNet.Emit;
5 |
6 | namespace dnlib.DotNet.Pdb {
7 | ///
8 | /// A local variable
9 | ///
10 | public sealed class PdbLocal : IHasCustomDebugInformation {
11 | ///
12 | /// Constructor
13 | ///
14 | public PdbLocal() {
15 | }
16 |
17 | ///
18 | /// Constructor
19 | ///
20 | ///
21 | ///
22 | ///
23 | public PdbLocal(Local local, string name, PdbLocalAttributes attributes) {
24 | Local = local;
25 | Name = name;
26 | Attributes = attributes;
27 | }
28 |
29 | ///
30 | /// Gets/sets the local
31 | ///
32 | public Local Local { get; set; }
33 |
34 | ///
35 | /// Gets/sets the name
36 | ///
37 | public string Name { get; set; }
38 |
39 | ///
40 | /// Gets/sets the attributes
41 | ///
42 | public PdbLocalAttributes Attributes { get; set; }
43 |
44 | ///
45 | /// Gets the index of the local
46 | ///
47 | public int Index => Local.Index;
48 |
49 | ///
50 | /// true if it should be hidden in debugger variables windows. Not all compiler generated locals have this flag set.
51 | ///
52 | public bool IsDebuggerHidden {
53 | get => (Attributes & PdbLocalAttributes.DebuggerHidden) != 0;
54 | set {
55 | if (value)
56 | Attributes |= PdbLocalAttributes.DebuggerHidden;
57 | else
58 | Attributes &= ~PdbLocalAttributes.DebuggerHidden;
59 | }
60 | }
61 |
62 | ///
63 | public int HasCustomDebugInformationTag => 24;
64 |
65 | ///
66 | public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0;
67 |
68 | ///
69 | /// Gets all custom debug infos
70 | ///
71 | public IList CustomDebugInfos => customDebugInfos;
72 | readonly IList customDebugInfos = new List();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/PdbLocalAttributes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet.Pdb {
6 | ///
7 | /// Local attributes
8 | ///
9 | [Flags]
10 | public enum PdbLocalAttributes {
11 | ///
12 | /// No bit is set
13 | ///
14 | None = 0,
15 |
16 | ///
17 | /// Local should be hidden in debugger variables windows. Not all compiler generated locals have this flag set.
18 | ///
19 | DebuggerHidden = 0x00000001,
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/PdbMethod.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Pdb {
4 | ///
5 | /// A PDB method
6 | ///
7 | public sealed class PdbMethod {
8 | ///
9 | /// Gets/sets the root scope. It contains all scopes of the method, using namespaces, variables and constants
10 | ///
11 | public PdbScope Scope { get; set; }
12 |
13 | ///
14 | /// Constructor
15 | ///
16 | public PdbMethod() {
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/PdbReaderContext.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using dnlib.IO;
5 | using dnlib.PE;
6 |
7 | namespace dnlib.DotNet.Pdb {
8 | readonly struct PdbReaderContext {
9 | readonly IPEImage peImage;
10 | readonly ImageDebugDirectory codeViewDebugDir;
11 |
12 | public bool HasDebugInfo => codeViewDebugDir is not null;
13 | public ImageDebugDirectory CodeViewDebugDirectory => codeViewDebugDir;
14 | public PdbReaderOptions Options { get; }
15 |
16 | public PdbReaderContext(IPEImage peImage, PdbReaderOptions options) {
17 | this.peImage = peImage;
18 | Options = options;
19 | codeViewDebugDir = TryGetDebugDirectoryEntry(peImage, ImageDebugType.CodeView);
20 | }
21 |
22 | public ImageDebugDirectory TryGetDebugDirectoryEntry(ImageDebugType imageDebugType) =>
23 | TryGetDebugDirectoryEntry(peImage, imageDebugType);
24 |
25 | static ImageDebugDirectory TryGetDebugDirectoryEntry(IPEImage peImage, ImageDebugType imageDebugType) {
26 | var list = peImage.ImageDebugDirectories;
27 | int count = list.Count;
28 | for (int i = 0; i < count; i++) {
29 | var entry = list[i];
30 | if (entry.Type == imageDebugType)
31 | return entry;
32 | }
33 | return null;
34 | }
35 |
36 | public bool TryGetCodeViewData(out Guid guid, out uint age) => TryGetCodeViewData(out guid, out age, out _);
37 |
38 | public bool TryGetCodeViewData(out Guid guid, out uint age, out string pdbFilename) {
39 | guid = Guid.Empty;
40 | age = 0;
41 | pdbFilename = null;
42 | var reader = GetCodeViewDataReader();
43 | // magic, guid, age, zero-terminated string
44 | if (reader.Length < 4 + 16 + 4 + 1)
45 | return false;
46 | if (reader.ReadUInt32() != 0x53445352)
47 | return false;
48 | guid = reader.ReadGuid();
49 | age = reader.ReadUInt32();
50 | pdbFilename = reader.TryReadZeroTerminatedUtf8String();
51 | return pdbFilename is not null;
52 | }
53 |
54 | DataReader GetCodeViewDataReader() {
55 | if (codeViewDebugDir is null)
56 | return default;
57 | return CreateReader(codeViewDebugDir.AddressOfRawData, codeViewDebugDir.SizeOfData);
58 | }
59 |
60 | public DataReader CreateReader(RVA rva, uint size) {
61 | if (rva == 0 || size == 0)
62 | return default;
63 | var reader = peImage.CreateReader(rva, size);
64 | if (reader.Length != size)
65 | return default;
66 | return reader;
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/PdbReaderOptions.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet.Pdb {
6 | ///
7 | /// PDB reader options
8 | ///
9 | [Flags]
10 | public enum PdbReaderOptions {
11 | ///
12 | /// No bit is set
13 | ///
14 | None = 0,
15 |
16 | ///
17 | /// Use the COM Windows PDB reader instead of the managed Windows PDB reader.
18 | ///
19 | /// This is NOT recommended since the COM reader can only be called on the same
20 | /// thread it was created on. It also requires a Windows OS.
21 | ///
22 | /// If this is not set, the managed PDB reader will be used.
23 | ///
24 | /// This option is only used if it's a Windows PDB file, not if it's a Portable PDB file.
25 | ///
26 | MicrosoftComReader = 0x00000001,
27 |
28 | ///
29 | /// Don't use Microsoft.DiaSymReader.Native. This is a NuGet package with an updated Windows PDB reader/writer implementation,
30 | /// and if it's available at runtime, dnlib will try to use it. If this option is set, dnlib won't use it.
31 | /// You have to add a reference to the NuGet package if you want to use it, dnlib has no reference to the NuGet package.
32 | ///
33 | /// Only used if is set and if it's a Windows PDB file
34 | ///
35 | NoDiaSymReader = 0x00000002,
36 |
37 | ///
38 | /// Don't use diasymreader.dll's PDB reader that is shipped with .NET Framework.
39 | ///
40 | /// Only used if is set and if it's a Windows PDB file
41 | ///
42 | NoOldDiaSymReader = 0x00000004,
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/PdbUtils.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Pdb {
4 | static class PdbUtils {
5 | public static bool IsEndInclusive(PdbFileKind pdbFileKind, Compiler compiler) =>
6 | pdbFileKind == PdbFileKind.WindowsPDB && compiler == Compiler.VisualBasic;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Portable/ImportDefinitionKindUtils.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Diagnostics;
4 |
5 | namespace dnlib.DotNet.Pdb.Portable {
6 | static class ImportDefinitionKindUtils {
7 | public const PdbImportDefinitionKind UNKNOWN_IMPORT_KIND = (PdbImportDefinitionKind)(-1);
8 |
9 | public static PdbImportDefinitionKind ToPdbImportDefinitionKind(uint value) {
10 | // See System.Reflection.Metadata.ImportDefinitionKind
11 | switch (value) {
12 | case 1: return PdbImportDefinitionKind.ImportNamespace;
13 | case 2: return PdbImportDefinitionKind.ImportAssemblyNamespace;
14 | case 3: return PdbImportDefinitionKind.ImportType;
15 | case 4: return PdbImportDefinitionKind.ImportXmlNamespace;
16 | case 5: return PdbImportDefinitionKind.ImportAssemblyReferenceAlias;
17 | case 6: return PdbImportDefinitionKind.AliasAssemblyReference;
18 | case 7: return PdbImportDefinitionKind.AliasNamespace;
19 | case 8: return PdbImportDefinitionKind.AliasAssemblyNamespace;
20 | case 9: return PdbImportDefinitionKind.AliasType;
21 | default:
22 | Debug.Fail($"Unknown import definition kind: 0x{value:X}");
23 | return UNKNOWN_IMPORT_KIND;
24 | }
25 | }
26 |
27 | public static bool ToImportDefinitionKind(PdbImportDefinitionKind kind, out uint rawKind) {
28 | switch (kind) {
29 | case PdbImportDefinitionKind.ImportNamespace: rawKind = 1; return true;
30 | case PdbImportDefinitionKind.ImportAssemblyNamespace: rawKind = 2; return true;
31 | case PdbImportDefinitionKind.ImportType: rawKind = 3; return true;
32 | case PdbImportDefinitionKind.ImportXmlNamespace: rawKind = 4; return true;
33 | case PdbImportDefinitionKind.ImportAssemblyReferenceAlias: rawKind = 5; return true;
34 | case PdbImportDefinitionKind.AliasAssemblyReference: rawKind = 6; return true;
35 | case PdbImportDefinitionKind.AliasNamespace: rawKind = 7; return true;
36 | case PdbImportDefinitionKind.AliasAssemblyNamespace: rawKind = 8; return true;
37 | case PdbImportDefinitionKind.AliasType: rawKind = 9; return true;
38 | default: rawKind = uint.MaxValue; return false;
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Portable/ListCache.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Collections.Generic;
4 | using System.Threading;
5 |
6 | namespace dnlib.DotNet.Pdb.Portable {
7 | static class ListCache {
8 | static volatile List cachedList;
9 | public static List AllocList() => Interlocked.Exchange(ref cachedList, null) ?? new List();
10 | public static void Free(ref List list) {
11 | list.Clear();
12 | cachedList = list;
13 | }
14 | public static T[] FreeAndToArray(ref List list) {
15 | var res = list.ToArray();
16 | Free(ref list);
17 | return res;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Portable/SequencePointConstants.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Pdb.Portable {
4 | static class SequencePointConstants {
5 | public const int HIDDEN_LINE = 0xFEEFEE;
6 | public const int HIDDEN_COLUMN = 0;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Portable/SymbolDocumentImpl.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Diagnostics;
5 | using System.Text;
6 | using dnlib.DotNet.Pdb.Symbols;
7 |
8 | namespace dnlib.DotNet.Pdb.Portable {
9 | [DebuggerDisplay("{GetDebuggerString(),nq}")]
10 | sealed class SymbolDocumentImpl : SymbolDocument {
11 | readonly string url;
12 | /*readonly*/ Guid language;
13 | /*readonly*/ Guid languageVendor;
14 | /*readonly*/ Guid documentType;
15 | /*readonly*/ Guid checkSumAlgorithmId;
16 | readonly byte[] checkSum;
17 | readonly PdbCustomDebugInfo[] customDebugInfos;
18 | MDToken mdToken;
19 |
20 | string GetDebuggerString() {
21 | var sb = new StringBuilder();
22 | if (language == PdbDocumentConstants.LanguageCSharp)
23 | sb.Append("C#");
24 | else if (language == PdbDocumentConstants.LanguageVisualBasic)
25 | sb.Append("VB");
26 | else if (language == PdbDocumentConstants.LanguageFSharp)
27 | sb.Append("F#");
28 | else
29 | sb.Append(language.ToString());
30 | sb.Append(", ");
31 | if (checkSumAlgorithmId == PdbDocumentConstants.HashSHA1)
32 | sb.Append("SHA-1");
33 | else if (checkSumAlgorithmId == PdbDocumentConstants.HashSHA256)
34 | sb.Append("SHA-256");
35 | else
36 | sb.Append(checkSumAlgorithmId.ToString());
37 | sb.Append(": ");
38 | sb.Append(url);
39 | return sb.ToString();
40 | }
41 |
42 | public override string URL => url;
43 | public override Guid Language => language;
44 | public override Guid LanguageVendor => languageVendor;
45 | public override Guid DocumentType => documentType;
46 | public override Guid CheckSumAlgorithmId => checkSumAlgorithmId;
47 | public override byte[] CheckSum => checkSum;
48 | public override PdbCustomDebugInfo[] CustomDebugInfos => customDebugInfos;
49 | public override MDToken? MDToken => mdToken;
50 |
51 | public SymbolDocumentImpl(string url, Guid language, Guid languageVendor, Guid documentType, Guid checkSumAlgorithmId, byte[] checkSum, PdbCustomDebugInfo[] customDebugInfos, MDToken mdToken) {
52 | this.url = url;
53 | this.language = language;
54 | this.languageVendor = languageVendor;
55 | this.documentType = documentType;
56 | this.checkSumAlgorithmId = checkSumAlgorithmId;
57 | this.checkSum = checkSum;
58 | this.customDebugInfos = customDebugInfos;
59 | this.mdToken = mdToken;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Portable/SymbolMethodImpl.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Collections.Generic;
4 | using dnlib.DotNet.Emit;
5 | using dnlib.DotNet.Pdb.Symbols;
6 |
7 | namespace dnlib.DotNet.Pdb.Portable {
8 | sealed class SymbolMethodImpl : SymbolMethod {
9 | readonly PortablePdbReader reader;
10 | readonly int token;
11 | readonly SymbolScope rootScope;
12 | readonly SymbolSequencePoint[] sequencePoints;
13 | readonly int kickoffMethod;
14 |
15 | public override int Token => token;
16 | public override SymbolScope RootScope => rootScope;
17 | public override IList SequencePoints => sequencePoints;
18 | public int KickoffMethod => kickoffMethod;
19 |
20 | public SymbolMethodImpl(PortablePdbReader reader, int token, SymbolScope rootScope, SymbolSequencePoint[] sequencePoints, int kickoffMethod) {
21 | this.reader = reader;
22 | this.token = token;
23 | this.rootScope = rootScope;
24 | this.sequencePoints = sequencePoints;
25 | this.kickoffMethod = kickoffMethod;
26 | }
27 |
28 | public override void GetCustomDebugInfos(MethodDef method, CilBody body, IList result) =>
29 | reader.GetCustomDebugInfos(this, method, body, result);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Portable/SymbolVariableImpl.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using dnlib.DotNet.Pdb.Symbols;
4 |
5 | namespace dnlib.DotNet.Pdb.Portable {
6 | sealed class SymbolVariableImpl : SymbolVariable {
7 | readonly string name;
8 | readonly PdbLocalAttributes attributes;
9 | readonly int index;
10 | readonly PdbCustomDebugInfo[] customDebugInfos;
11 |
12 | public override string Name => name;
13 | public override PdbLocalAttributes Attributes => attributes;
14 | public override int Index => index;
15 | public override PdbCustomDebugInfo[] CustomDebugInfos => customDebugInfos;
16 |
17 | public SymbolVariableImpl(string name, PdbLocalAttributes attributes, int index, PdbCustomDebugInfo[] customDebugInfos) {
18 | this.name = name;
19 | this.attributes = attributes;
20 | this.index = index;
21 | this.customDebugInfos = customDebugInfos;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/SequencePoint.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Diagnostics;
4 |
5 | namespace dnlib.DotNet.Pdb {
6 | ///
7 | /// PDB sequence point
8 | ///
9 | [DebuggerDisplay("({StartLine}, {StartColumn}) - ({EndLine}, {EndColumn}) {Document.Url}")]
10 | public sealed class SequencePoint {
11 | ///
12 | /// PDB document
13 | ///
14 | public PdbDocument Document { get; set; }
15 |
16 | ///
17 | /// Start line
18 | ///
19 | public int StartLine { get; set; }
20 |
21 | ///
22 | /// Start column
23 | ///
24 | public int StartColumn { get; set; }
25 |
26 | ///
27 | /// End line
28 | ///
29 | public int EndLine { get; set; }
30 |
31 | ///
32 | /// End column
33 | ///
34 | public int EndColumn { get; set; }
35 |
36 | ///
37 | /// Clones this instance
38 | ///
39 | /// A new cloned instance
40 | public SequencePoint Clone() {
41 | return new SequencePoint() {
42 | Document = Document,
43 | StartLine = StartLine,
44 | StartColumn = StartColumn,
45 | EndLine = EndLine,
46 | EndColumn = EndColumn,
47 | };
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Symbols/SymbolAsyncStepInfo.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Pdb.Symbols {
4 | ///
5 | /// Async step info
6 | ///
7 | public struct SymbolAsyncStepInfo {
8 | ///
9 | /// Yield offset
10 | ///
11 | public uint YieldOffset;
12 |
13 | ///
14 | /// Breakpoint offset
15 | ///
16 | public uint BreakpointOffset;
17 |
18 | ///
19 | /// Breakpoint method token
20 | ///
21 | public uint BreakpointMethod;
22 |
23 | ///
24 | /// Constructor
25 | ///
26 | /// Yield offset
27 | /// Breakpoint offset
28 | /// Breakpoint method token
29 | public SymbolAsyncStepInfo(uint yieldOffset, uint breakpointOffset, uint breakpointMethod) {
30 | YieldOffset = yieldOffset;
31 | BreakpointOffset = breakpointOffset;
32 | BreakpointMethod = breakpointMethod;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Symbols/SymbolDocument.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet.Pdb.Symbols {
6 | ///
7 | /// A document
8 | ///
9 | public abstract class SymbolDocument {
10 | ///
11 | /// Gets the URL
12 | ///
13 | public abstract string URL { get; }
14 |
15 | ///
16 | /// Gets the language
17 | ///
18 | public abstract Guid Language { get; }
19 |
20 | ///
21 | /// Gets the language vendor
22 | ///
23 | public abstract Guid LanguageVendor { get; }
24 |
25 | ///
26 | /// Gets the document type
27 | ///
28 | public abstract Guid DocumentType { get; }
29 |
30 | ///
31 | /// Gets the checksum algorithm id
32 | ///
33 | public abstract Guid CheckSumAlgorithmId { get; }
34 |
35 | ///
36 | /// Gets the checksum
37 | ///
38 | public abstract byte[] CheckSum { get; }
39 |
40 | ///
41 | /// Gets the custom debug infos
42 | ///
43 | public abstract PdbCustomDebugInfo[] CustomDebugInfos { get; }
44 |
45 | ///
46 | /// Gets the Metadata token of the document if available.
47 | ///
48 | public abstract MDToken? MDToken { get; }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Symbols/SymbolMethod.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Collections.Generic;
4 | using dnlib.DotNet.Emit;
5 |
6 | namespace dnlib.DotNet.Pdb.Symbols {
7 | ///
8 | /// A method
9 | ///
10 | public abstract class SymbolMethod {
11 | ///
12 | /// Gets the method token
13 | ///
14 | public abstract int Token { get; }
15 |
16 | ///
17 | /// Gets the root scope
18 | ///
19 | public abstract SymbolScope RootScope { get; }
20 |
21 | ///
22 | /// Gets all sequence points
23 | ///
24 | public abstract IList SequencePoints { get; }
25 |
26 | ///
27 | /// Reads custom debug info
28 | ///
29 | /// Method
30 | /// Method body
31 | /// Updated with custom debug info
32 | public abstract void GetCustomDebugInfos(MethodDef method, CilBody body, IList result);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Symbols/SymbolNamespace.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Pdb.Symbols {
4 | ///
5 | /// A namespace
6 | ///
7 | public abstract class SymbolNamespace {
8 | ///
9 | /// Gets the name
10 | ///
11 | public abstract string Name { get; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Symbols/SymbolReader.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Collections.Generic;
5 |
6 | namespace dnlib.DotNet.Pdb.Symbols {
7 | ///
8 | /// Reads symbols from a PDB file
9 | ///
10 | public abstract class SymbolReader : IDisposable {
11 | ///
12 | /// Called by the owner module before any other methods and properties are called
13 | ///
14 | /// Owner module
15 | public abstract void Initialize(ModuleDef module);
16 |
17 | ///
18 | /// Gets the PDB file kind
19 | ///
20 | public abstract PdbFileKind PdbFileKind { get; }
21 |
22 | ///
23 | /// Gets the user entry point token or 0 if none
24 | ///
25 | public abstract int UserEntryPoint { get; }
26 |
27 | ///
28 | /// Gets all documents
29 | ///
30 | public abstract IList Documents { get; }
31 |
32 | ///
33 | /// Gets a method or returns null if the method doesn't exist in the PDB file
34 | ///
35 | /// Method
36 | /// Edit and continue version. The first version is 1
37 | ///
38 | public abstract SymbolMethod GetMethod(MethodDef method, int version);
39 |
40 | ///
41 | /// Reads custom debug info
42 | ///
43 | /// Token of a instance
44 | /// Generic parameter context
45 | /// Updated with custom debug info
46 | public abstract void GetCustomDebugInfos(int token, GenericParamContext gpContext, IList result);
47 |
48 | ///
49 | /// Cleans up resources
50 | ///
51 | public virtual void Dispose() {
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Symbols/SymbolScope.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Collections.Generic;
4 |
5 | namespace dnlib.DotNet.Pdb.Symbols {
6 | ///
7 | /// A scope
8 | ///
9 | public abstract class SymbolScope {
10 | ///
11 | /// Gets the method
12 | ///
13 | public abstract SymbolMethod Method { get; }
14 |
15 | ///
16 | /// Gets the parent scope
17 | ///
18 | public abstract SymbolScope Parent { get; }
19 |
20 | ///
21 | /// Gets the start offset of the scope in the method
22 | ///
23 | public abstract int StartOffset { get; }
24 |
25 | ///
26 | /// Gets the end offset of the scope in the method
27 | ///
28 | public abstract int EndOffset { get; }
29 |
30 | ///
31 | /// Gets all child scopes
32 | ///
33 | public abstract IList Children { get; }
34 |
35 | ///
36 | /// Gets all locals defined in this scope
37 | ///
38 | public abstract IList Locals { get; }
39 |
40 | ///
41 | /// Gets all namespaces in this scope
42 | ///
43 | public abstract IList Namespaces { get; }
44 |
45 | ///
46 | /// Gets all custom debug infos
47 | ///
48 | public abstract IList CustomDebugInfos { get; }
49 |
50 | ///
51 | /// Gets the import scope or null if none
52 | ///
53 | public abstract PdbImportScope ImportScope { get; }
54 |
55 | ///
56 | /// Gets all the constants
57 | ///
58 | /// Owner module if a signature must be read from the #Blob
59 | /// Generic parameter context
60 | ///
61 | public abstract IList GetConstants(ModuleDef module, GenericParamContext gpContext);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Symbols/SymbolSequencePoint.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Diagnostics;
4 | using System.Text;
5 |
6 | namespace dnlib.DotNet.Pdb.Symbols {
7 | ///
8 | /// Sequence point
9 | ///
10 | [DebuggerDisplay("{GetDebuggerString(),nq}")]
11 | public struct SymbolSequencePoint {
12 | ///
13 | /// IL offset
14 | ///
15 | public int Offset;
16 |
17 | ///
18 | /// Document
19 | ///
20 | public SymbolDocument Document;
21 |
22 | ///
23 | /// Start line
24 | ///
25 | public int Line;
26 |
27 | ///
28 | /// Start column
29 | ///
30 | public int Column;
31 |
32 | ///
33 | /// End line
34 | ///
35 | public int EndLine;
36 |
37 | ///
38 | /// End column
39 | ///
40 | public int EndColumn;
41 |
42 | readonly string GetDebuggerString() {
43 | var sb = new StringBuilder();
44 | if (Line == 0xFEEFEE && EndLine == 0xFEEFEE)
45 | sb.Append("");
46 | else {
47 | sb.Append("(");
48 | sb.Append(Line);
49 | sb.Append(",");
50 | sb.Append(Column);
51 | sb.Append(")-(");
52 | sb.Append(EndLine);
53 | sb.Append(",");
54 | sb.Append(EndColumn);
55 | sb.Append(")");
56 | }
57 | sb.Append(": ");
58 | sb.Append(Document.URL);
59 | return sb.ToString();
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/Symbols/SymbolVariable.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Pdb.Symbols {
4 | ///
5 | /// A variable
6 | ///
7 | public abstract class SymbolVariable {
8 | ///
9 | /// Gets the name
10 | ///
11 | public abstract string Name { get; }
12 |
13 | ///
14 | /// Gets the attributes
15 | ///
16 | public abstract PdbLocalAttributes Attributes { get; }
17 |
18 | ///
19 | /// Gets the index of the variable
20 | ///
21 | public abstract int Index { get; }
22 |
23 | ///
24 | /// Gets all custom debug infos
25 | ///
26 | public abstract PdbCustomDebugInfo[] CustomDebugInfos { get; }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/WindowsPdb/CorSymVarFlag.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet.Pdb.WindowsPdb {
6 | [Flags]
7 | enum CorSymVarFlag : uint {
8 | VAR_IS_COMP_GEN = 0x00000001,
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/WindowsPdb/CustomDebugInfoConstants.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Pdb.WindowsPdb {
4 | static class CustomDebugInfoConstants {
5 | public const int Version = 4;
6 | public const int RecordVersion = 4;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/DotNet/Pdb/WindowsPdb/SymbolWriter.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Diagnostics.SymbolStore;
5 | using dnlib.DotNet.Writer;
6 |
7 | namespace dnlib.DotNet.Pdb.WindowsPdb {
8 | abstract class SymbolWriter : IDisposable {
9 | public abstract bool IsDeterministic { get; }
10 | public abstract bool SupportsAsyncMethods { get; }
11 |
12 | public abstract void Initialize(Metadata metadata);
13 | public abstract void Close();
14 | public abstract bool GetDebugInfo(ChecksumAlgorithm pdbChecksumAlgorithm, ref uint pdbAge, out Guid guid, out uint stamp, out IMAGE_DEBUG_DIRECTORY pIDD, out byte[] codeViewData);
15 |
16 | public abstract void SetUserEntryPoint(MDToken entryMethod);
17 | public abstract ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType);
18 | public abstract void SetSourceServerData(byte[] data);
19 | public abstract void SetSourceLinkData(byte[] data);
20 |
21 | public abstract void OpenMethod(MDToken method);
22 | public abstract void CloseMethod();
23 | public abstract int OpenScope(int startOffset);
24 | public abstract void CloseScope(int endOffset);
25 | public abstract void SetSymAttribute(MDToken parent, string name, byte[] data);
26 | public abstract void UsingNamespace(string fullName);
27 | public abstract void DefineSequencePoints(ISymbolDocumentWriter document, uint arraySize, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns);
28 | public abstract void DefineLocalVariable(string name, uint attributes, uint sigToken, uint addrKind, uint addr1, uint addr2, uint addr3, uint startOffset, uint endOffset);
29 | public abstract void DefineConstant(string name, object value, uint sigToken);
30 | public abstract void DefineKickoffMethod(uint kickoffMethod);
31 | public abstract void DefineCatchHandlerILOffset(uint catchHandlerOffset);
32 | public abstract void DefineAsyncStepInfo(uint[] yieldOffsets, uint[] breakpointOffset, uint[] breakpointMethod);
33 |
34 | public abstract void Dispose();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/DotNet/PropertyAttributes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Property attributes, see CorHdr.h/CorPropertyAttr
8 | ///
9 | [Flags]
10 | public enum PropertyAttributes : ushort {
11 | /// property is special. Name describes how.
12 | SpecialName = 0x0200,
13 | /// Runtime(metadata internal APIs) should check name encoding.
14 | RTSpecialName = 0x0400,
15 | /// Property has default
16 | HasDefault = 0x1000,
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/DotNet/PublicKey.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Threading;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Represents a public key
8 | ///
9 | public sealed class PublicKey : PublicKeyBase {
10 | const AssemblyHashAlgorithm DEFAULT_ALGORITHM = AssemblyHashAlgorithm.SHA1;
11 | PublicKeyToken publicKeyToken;
12 |
13 | ///
14 | /// Gets the
15 | ///
16 | public override PublicKeyToken Token {
17 | get {
18 | if (publicKeyToken is null && !IsNullOrEmpty)
19 | Interlocked.CompareExchange(ref publicKeyToken, AssemblyHash.CreatePublicKeyToken(data), null);
20 | return publicKeyToken;
21 | }
22 | }
23 |
24 | ///
25 | public override byte[] Data => data;
26 |
27 | ///
28 | /// Constructor
29 | ///
30 | public PublicKey() : base((byte[])null) { }
31 |
32 | ///
33 | /// Constructor
34 | ///
35 | /// Public key data
36 | public PublicKey(byte[] data)
37 | : base(data) {
38 | }
39 |
40 | ///
41 | /// Constructor
42 | ///
43 | /// Public key data as a hex string or the string "null"
44 | /// to set public key data to null
45 | public PublicKey(string hexString)
46 | : base(hexString) {
47 | }
48 |
49 | ///
50 | public override bool Equals(object obj) {
51 | if ((object)this == obj)
52 | return true;
53 | var other = obj as PublicKey;
54 | if (other is null)
55 | return false;
56 | return Utils.Equals(Data, other.Data);
57 | }
58 |
59 | ///
60 | public override int GetHashCode() => Utils.GetHashCode(Data);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/DotNet/PublicKeyToken.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet {
4 | ///
5 | /// Represents a public key token
6 | ///
7 | public sealed class PublicKeyToken : PublicKeyBase {
8 | ///
9 | /// Gets the
10 | ///
11 | public override PublicKeyToken Token => this;
12 |
13 | ///
14 | /// Constructor
15 | ///
16 | public PublicKeyToken() : base((byte[])null) { }
17 |
18 | ///
19 | public PublicKeyToken(byte[] data)
20 | : base(data) {
21 | }
22 |
23 | ///
24 | public PublicKeyToken(string hexString)
25 | : base(hexString) {
26 | }
27 |
28 | ///
29 | public override bool Equals(object obj) {
30 | if ((object)this == obj)
31 | return true;
32 | var other = obj as PublicKeyToken;
33 | if (other is null)
34 | return false;
35 | return Utils.Equals(Data, other.Data);
36 | }
37 |
38 | ///
39 | public override int GetHashCode() => Utils.GetHashCode(Data);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/DotNet/RecursionCounter.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet {
6 | ///
7 | /// Recursion counter
8 | ///
9 | struct RecursionCounter {
10 | ///
11 | /// Max recursion count. If this is reached, we won't continue, and will use a default value.
12 | ///
13 | public const int MAX_RECURSION_COUNT = 100;
14 | int counter;
15 |
16 | ///
17 | /// Gets the recursion counter
18 | ///
19 | public int Counter => counter;
20 |
21 | ///
22 | /// Increments if it's not too high. ALL instance methods
23 | /// that can be called recursively must call this method and
24 | /// (if this method returns true)
25 | ///
26 | /// true if it was incremented and caller can continue, false if
27 | /// it was not incremented and the caller must return to its caller.
28 | public bool Increment() {
29 | if (counter >= MAX_RECURSION_COUNT)
30 | return false;
31 | counter++;
32 | return true;
33 | }
34 |
35 | ///
36 | /// Must be called before returning to caller if
37 | /// returned true.
38 | ///
39 | public void Decrement() {
40 | #if DEBUG
41 | if (counter <= 0)
42 | throw new InvalidOperationException("recursionCounter <= 0");
43 | #endif
44 | counter--;
45 | }
46 |
47 | ///
48 | public override string ToString() => counter.ToString();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/DotNet/Resources/IResourceData.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.IO;
4 | using System.Runtime.Serialization;
5 | using dnlib.IO;
6 |
7 | namespace dnlib.DotNet.Resources {
8 | ///
9 | /// Implemented by all resource data
10 | ///
11 | public interface IResourceData : IFileSection {
12 | ///
13 | /// Gets the type of data
14 | ///
15 | ResourceTypeCode Code { get; }
16 |
17 | ///
18 | /// Start offset of the section in the file
19 | ///
20 | new FileOffset StartOffset { get; set; }
21 |
22 | ///
23 | /// End offset of the section in the file. This is one byte after the last
24 | /// valid offset in the section.
25 | ///
26 | new FileOffset EndOffset { get; set; }
27 |
28 | ///
29 | /// Writes the data
30 | ///
31 | /// Writer
32 | /// Formatter if needed by implementer
33 | void WriteData(ResourceBinaryWriter writer, IFormatter formatter);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/DotNet/Resources/ResourceBinaryWriter.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace dnlib.DotNet.Resources {
4 | ///
5 | /// Extension of for writing resource set elements
6 | ///
7 | public sealed class ResourceBinaryWriter : BinaryWriter {
8 | ///
9 | /// Format version of the resource set
10 | ///
11 | public int FormatVersion { get; internal set; }
12 |
13 | ///
14 | /// Specifies the target reader type of the resource set
15 | ///
16 | public ResourceReaderType ReaderType { get; internal set; }
17 |
18 | internal ResourceBinaryWriter(Stream stream) : base(stream) { }
19 |
20 | ///
21 | /// Writes a 7-bit encoded integer.
22 | ///
23 | /// The value to write
24 | public new void Write7BitEncodedInt(int value) => base.Write7BitEncodedInt(value);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/DotNet/Resources/ResourceElement.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Resources {
4 | ///
5 | /// Resource element
6 | ///
7 | public sealed class ResourceElement {
8 | ///
9 | /// Name of resource
10 | ///
11 | public string Name { get; set; }
12 |
13 | ///
14 | /// Data of resource
15 | ///
16 | public IResourceData ResourceData { get; set; }
17 |
18 | ///
19 | public override string ToString() => $"N: {Name}, V: {ResourceData}";
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/DotNet/Resources/ResourceReaderType.cs:
--------------------------------------------------------------------------------
1 | namespace dnlib.DotNet.Resources {
2 | ///
3 | /// Resource reader type
4 | ///
5 | public enum ResourceReaderType {
6 | ///
7 | /// System.Resources.ResourceReader
8 | ///
9 | ResourceReader,
10 | ///
11 | /// System.Resources.Extensions.DeserializingResourceReader
12 | ///
13 | DeserializingResourceReader,
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/DotNet/Resources/ResourceTypeCode.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Resources {
4 | ///
5 | /// Type of resource
6 | ///
7 | public enum ResourceTypeCode {
8 | ///
9 | /// null
10 | ///
11 | Null = 0,
12 |
13 | ///
14 | ///
15 | ///
16 | String = 1,
17 |
18 | ///
19 | ///
20 | ///
21 | Boolean = 2,
22 |
23 | ///
24 | ///
25 | ///
26 | Char = 3,
27 |
28 | ///
29 | ///
30 | ///
31 | Byte = 4,
32 |
33 | ///
34 | ///
35 | ///
36 | SByte = 5,
37 |
38 | ///
39 | ///
40 | ///
41 | Int16 = 6,
42 |
43 | ///
44 | ///
45 | ///
46 | UInt16 = 7,
47 |
48 | ///
49 | ///
50 | ///
51 | Int32 = 8,
52 |
53 | ///
54 | ///
55 | ///
56 | UInt32 = 9,
57 |
58 | ///
59 | ///
60 | ///
61 | Int64 = 0x0A,
62 |
63 | ///
64 | ///
65 | ///
66 | UInt64 = 0x0B,
67 |
68 | ///
69 | ///
70 | ///
71 | Single = 0x0C,
72 |
73 | ///
74 | ///
75 | ///
76 | Double = 0x0D,
77 |
78 | ///
79 | ///
80 | ///
81 | Decimal = 0x0E,
82 |
83 | ///
84 | ///
85 | ///
86 | DateTime = 0x0F,
87 |
88 | ///
89 | ///
90 | ///
91 | TimeSpan = 0x10,
92 |
93 | ///
94 | /// array
95 | ///
96 | ByteArray = 0x20,
97 |
98 | ///
99 | ///
100 | ///
101 | Stream = 0x21,
102 |
103 | ///
104 | /// Start of user types
105 | ///
106 | UserTypes = 0x40,
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/DotNet/Resources/UserResourceType.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Resources {
4 | ///
5 | /// User resource type
6 | ///
7 | public sealed class UserResourceType {
8 | readonly string name;
9 | readonly ResourceTypeCode code;
10 |
11 | ///
12 | /// Full name including assembly of type
13 | ///
14 | public string Name => name;
15 |
16 | ///
17 | /// User type code
18 | ///
19 | public ResourceTypeCode Code => code;
20 |
21 | ///
22 | /// Constructor
23 | ///
24 | /// Full name including assembly of type
25 | /// User type code
26 | public UserResourceType(string name, ResourceTypeCode code) {
27 | this.name = name;
28 | this.code = code;
29 | }
30 |
31 | ///
32 | public override string ToString() => $"{(int)code:X2} {name}";
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/DotNet/SecurityAction.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet {
4 | ///
5 | /// Security action. See CorHdr.h/CorDeclSecurity
6 | ///
7 | public enum SecurityAction : short {
8 | /// Mask allows growth of enum.
9 | ActionMask = 0x001F,
10 | ///
11 | ActionNil = 0x0000,
12 | ///
13 | Request = 0x0001,
14 | ///
15 | Demand = 0x0002,
16 | ///
17 | Assert = 0x0003,
18 | ///
19 | Deny = 0x0004,
20 | ///
21 | PermitOnly = 0x0005,
22 | ///
23 | LinktimeCheck = 0x0006,
24 | ///
25 | LinkDemand = LinktimeCheck,
26 | ///
27 | InheritanceCheck = 0x0007,
28 | ///
29 | InheritDemand = InheritanceCheck,
30 | ///
31 | RequestMinimum = 0x0008,
32 | ///
33 | RequestOptional = 0x0009,
34 | ///
35 | RequestRefuse = 0x000A,
36 | /// Persisted grant set at prejit time
37 | PrejitGrant = 0x000B,
38 | /// Persisted grant set at prejit time
39 | PreJitGrant = PrejitGrant,
40 | /// Persisted denied set at prejit time
41 | PrejitDenied = 0x000C,
42 | /// Persisted denied set at prejit time
43 | PreJitDeny = PrejitDenied,
44 | ///
45 | NonCasDemand = 0x000D,
46 | ///
47 | NonCasLinkDemand = 0x000E,
48 | ///
49 | NonCasInheritance = 0x000F,
50 | /// Maximum legal value
51 | MaximumValue = 0x000F,
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/DotNet/SerializationType.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet {
4 | ///
5 | /// See CorSerializationType/CorHdr.h
6 | ///
7 | enum SerializationType : byte {
8 | ///
9 | Undefined = 0,
10 | /// System.Boolean
11 | Boolean = ElementType.Boolean,
12 | /// System.Char
13 | Char = ElementType.Char,
14 | /// System.SByte
15 | I1 = ElementType.I1,
16 | /// System.Byte
17 | U1 = ElementType.U1,
18 | /// System.Int16
19 | I2 = ElementType.I2,
20 | /// System.UInt16
21 | U2 = ElementType.U2,
22 | /// System.Int32
23 | I4 = ElementType.I4,
24 | /// System.UInt32
25 | U4 = ElementType.U4,
26 | /// System.Int64
27 | I8 = ElementType.I8,
28 | /// System.UInt64
29 | U8 = ElementType.U8,
30 | /// System.Single
31 | R4 = ElementType.R4,
32 | /// System.Double
33 | R8 = ElementType.R8,
34 | /// System.String
35 | String = ElementType.String,
36 | /// Single-dimension, zero lower bound array ([])
37 | SZArray = ElementType.SZArray,
38 | /// System.Type
39 | Type = 0x50,
40 | /// Boxed value type
41 | TaggedObject= 0x51,
42 | /// A field
43 | Field = 0x53,
44 | /// A property
45 | Property = 0x54,
46 | /// An enum
47 | Enum = 0x55,
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/DotNet/WinMDStatus.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet {
4 | ///
5 | /// WinMD status
6 | ///
7 | public enum WinMDStatus {
8 | ///
9 | /// This is not a WinMD file
10 | ///
11 | None,
12 |
13 | ///
14 | /// This is a pure WinMD file (not managed)
15 | ///
16 | Pure,
17 |
18 | ///
19 | /// This is a managed WinMD file (created by eg. winmdexp.exe)
20 | ///
21 | Managed,
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/ByteArrayChunk.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using dnlib.IO;
5 | using dnlib.PE;
6 |
7 | namespace dnlib.DotNet.Writer {
8 | ///
9 | /// Stores a byte array
10 | ///
11 | public sealed class ByteArrayChunk : IReuseChunk {
12 | readonly byte[] array;
13 | readonly uint alignment;
14 | FileOffset offset;
15 | RVA rva;
16 |
17 | ///
18 | public FileOffset FileOffset => offset;
19 |
20 | ///
21 | public RVA RVA => rva;
22 |
23 | ///
24 | /// Gets the data
25 | ///
26 | public byte[] Data => array;
27 |
28 | ///
29 | /// Constructor
30 | ///
31 | /// The data. It will be owned by this instance and can't be modified by
32 | /// other code if this instance is inserted as a key in a dictionary (because
33 | /// return value will be different if you modify the array). If
34 | /// it's never inserted as a key in a dictionary, then the contents can be modified,
35 | /// but shouldn't be resized after has been called.
36 | /// The alignment of the data
37 | public ByteArrayChunk(byte[] array, uint alignment = 0) {
38 | this.array = array ?? Array2.Empty();
39 | this.alignment = alignment;
40 | }
41 |
42 | bool IReuseChunk.CanReuse(RVA origRva, uint origSize) => (uint)array.Length <= origSize;
43 |
44 | ///
45 | public void SetOffset(FileOffset offset, RVA rva) {
46 | this.offset = offset;
47 | this.rva = rva;
48 | }
49 |
50 | ///
51 | public uint GetFileLength() => (uint)array.Length;
52 |
53 | ///
54 | public uint GetVirtualSize() => GetFileLength();
55 |
56 | ///
57 | public uint CalculateAlignment() => alignment;
58 |
59 | ///
60 | public void WriteTo(DataWriter writer) => writer.WriteBytes(array);
61 |
62 | ///
63 | public override int GetHashCode() => Utils.GetHashCode(array);
64 |
65 | ///
66 | public override bool Equals(object obj) {
67 | var other = obj as ByteArrayChunk;
68 | return other is not null && Utils.Equals(array, other.array);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/ChecksumAlgorithm.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Writer {
4 | ///
5 | /// Checksum algorithm
6 | ///
7 | public enum ChecksumAlgorithm {
8 | ///
9 | /// SHA-1
10 | ///
11 | SHA1,
12 |
13 | ///
14 | /// SHA-256
15 | ///
16 | SHA256,
17 |
18 | ///
19 | /// SHA-384
20 | ///
21 | SHA384,
22 |
23 | ///
24 | /// SHA-512
25 | ///
26 | SHA512,
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/ChunkList.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Collections.Generic;
5 |
6 | namespace dnlib.DotNet.Writer {
7 | ///
8 | /// Contains a list of s
9 | ///
10 | public class ChunkList : ChunkListBase where T : class, IChunk {
11 | ///
12 | /// Default constructor
13 | ///
14 | public ChunkList() => chunks = new List();
15 |
16 | ///
17 | /// Add a
18 | ///
19 | /// The chunk to add or null if none
20 | /// Chunk alignment
21 | public void Add(T chunk, uint alignment) {
22 | if (setOffsetCalled)
23 | throw new InvalidOperationException("SetOffset() has already been called");
24 | if (chunk is not null)
25 | chunks.Add(new Elem(chunk, alignment));
26 | }
27 |
28 | ///
29 | /// Remove a
30 | ///
31 | /// The chunk to remove or null if none
32 | /// Alignment of the chunk, or null if the chunk cannot be removed.
33 | public uint? Remove(T chunk) {
34 | if (setOffsetCalled)
35 | throw new InvalidOperationException("SetOffset() has already been called");
36 | if (chunk is not null) {
37 | var chunks = this.chunks;
38 | for (int i = 0; i < chunks.Count; i++) {
39 | if (chunks[i].chunk == chunk) {
40 | uint alignment = chunks[i].alignment;
41 | chunks.RemoveAt(i);
42 | return alignment;
43 | }
44 | }
45 | }
46 | return null;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/DataReaderHeap.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using dnlib.DotNet.MD;
5 | using dnlib.IO;
6 |
7 | namespace dnlib.DotNet.Writer {
8 | ///
9 | /// Copies existing data to a new metadata heap
10 | ///
11 | public sealed class DataReaderHeap : HeapBase {
12 | ///
13 | /// Gets the name of the heap
14 | ///
15 | public override string Name { get; }
16 |
17 | internal DotNetStream OptionalOriginalStream { get; }
18 |
19 | readonly DataReader heapReader;
20 |
21 | ///
22 | /// Constructor
23 | ///
24 | /// The stream whose data will be copied to the new metadata file
25 | public DataReaderHeap(DotNetStream stream) {
26 | OptionalOriginalStream = stream ?? throw new ArgumentNullException(nameof(stream));
27 | heapReader = stream.CreateReader();
28 | Name = stream.Name;
29 | }
30 |
31 | ///
32 | /// Constructor
33 | ///
34 | /// Heap name
35 | /// Heap content
36 | public DataReaderHeap(string name, DataReader heapReader) {
37 | this.heapReader = heapReader;
38 | this.heapReader.Position = 0;
39 | Name = name ?? throw new ArgumentNullException(nameof(name));
40 | }
41 |
42 | ///
43 | public override uint GetRawLength() => heapReader.Length;
44 |
45 | ///
46 | protected override void WriteToImpl(DataWriter writer) => heapReader.CopyTo(writer);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/Extensions.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Writer {
4 | ///
5 | /// Extension methods
6 | ///
7 | static partial class Extensions {
8 | ///
9 | /// Write zeros
10 | ///
11 | /// this
12 | /// Number of zeros
13 | public static void WriteZeroes(this DataWriter writer, int count) {
14 | while (count >= 8) {
15 | writer.WriteUInt64(0);
16 | count -= 8;
17 | }
18 | for (int i = 0; i < count; i++)
19 | writer.WriteByte(0);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/GuidHeap.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Collections.Generic;
5 |
6 | namespace dnlib.DotNet.Writer {
7 | ///
8 | /// #GUID heap
9 | ///
10 | public sealed class GuidHeap : HeapBase, IOffsetHeap {
11 | readonly Dictionary guids = new Dictionary();
12 | Dictionary userRawData;
13 |
14 | ///
15 | public override string Name => "#GUID";
16 |
17 | ///
18 | /// Adds a guid to the #GUID heap
19 | ///
20 | /// The guid
21 | /// The index of the guid in the #GUID heap
22 | public uint Add(Guid? guid) {
23 | if (isReadOnly)
24 | throw new ModuleWriterException("Trying to modify #GUID when it's read-only");
25 | if (guid is null)
26 | return 0;
27 |
28 | if (guids.TryGetValue(guid.Value, out uint index))
29 | return index;
30 |
31 | index = (uint)guids.Count + 1;
32 | guids.Add(guid.Value, index);
33 | return index;
34 | }
35 |
36 | ///
37 | public override uint GetRawLength() => (uint)guids.Count * 16;
38 |
39 | ///
40 | protected override void WriteToImpl(DataWriter writer) {
41 | uint offset = 0;
42 | foreach (var kv in guids) {
43 | if (userRawData is null || !userRawData.TryGetValue(offset, out var rawData))
44 | rawData = kv.Key.ToByteArray();
45 | writer.WriteBytes(rawData);
46 | offset += 16;
47 | }
48 | }
49 |
50 | ///
51 | public int GetRawDataSize(Guid data) => 16;
52 |
53 | ///
54 | public void SetRawData(uint offset, byte[] rawData) {
55 | if (rawData is null || rawData.Length != 16)
56 | throw new ArgumentException("Invalid size of GUID raw data");
57 | if (userRawData is null)
58 | userRawData = new Dictionary();
59 | userRawData[offset] = rawData;
60 | }
61 |
62 | ///
63 | public IEnumerable> GetAllRawData() {
64 | uint offset = 0;
65 | foreach (var kv in guids) {
66 | yield return new KeyValuePair(offset, kv.Key.ToByteArray());
67 | offset += 16;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/Hasher.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.IO;
5 | using System.Security.Cryptography;
6 |
7 | namespace dnlib.DotNet.Writer {
8 | static class Hasher {
9 | static HashAlgorithm CreateHasher(ChecksumAlgorithm checksumAlgorithm) =>
10 | checksumAlgorithm switch {
11 | ChecksumAlgorithm.SHA1 => SHA1.Create(),
12 | ChecksumAlgorithm.SHA256 => SHA256.Create(),
13 | ChecksumAlgorithm.SHA384 => SHA384.Create(),
14 | ChecksumAlgorithm.SHA512 => SHA512.Create(),
15 | _ => throw new ArgumentOutOfRangeException(nameof(checksumAlgorithm)),
16 | };
17 |
18 | public static string GetChecksumName(ChecksumAlgorithm checksumAlgorithm) =>
19 | // https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PE-COFF.md#pdb-checksum-debug-directory-entry-type-19
20 | checksumAlgorithm switch {
21 | ChecksumAlgorithm.SHA1 => "SHA1",
22 | ChecksumAlgorithm.SHA256 => "SHA256",
23 | ChecksumAlgorithm.SHA384 => "SHA384",
24 | ChecksumAlgorithm.SHA512 => "SHA512",
25 | _ => throw new ArgumentOutOfRangeException(nameof(checksumAlgorithm)),
26 | };
27 |
28 | public static bool TryGetChecksumAlgorithm(string checksumName, out ChecksumAlgorithm pdbChecksumAlgorithm, out int checksumSize) {
29 | switch (checksumName) {
30 | case "SHA1":
31 | pdbChecksumAlgorithm = ChecksumAlgorithm.SHA1;
32 | checksumSize = 20;
33 | return true;
34 |
35 | case "SHA256":
36 | pdbChecksumAlgorithm = ChecksumAlgorithm.SHA256;
37 | checksumSize = 32;
38 | return true;
39 |
40 | case "SHA384":
41 | pdbChecksumAlgorithm = ChecksumAlgorithm.SHA384;
42 | checksumSize = 48;
43 | return true;
44 |
45 | case "SHA512":
46 | pdbChecksumAlgorithm = ChecksumAlgorithm.SHA512;
47 | checksumSize = 64;
48 | return true;
49 |
50 | default:
51 | pdbChecksumAlgorithm = 0;
52 | checksumSize = -1;
53 | return false;
54 | }
55 | }
56 |
57 | public static byte[] Hash(ChecksumAlgorithm checksumAlgorithm, Stream stream, long length) {
58 | var buffer = new byte[(int)Math.Min(0x2000, length)];
59 | using (var hasher = CreateHasher(checksumAlgorithm)) {
60 | while (length > 0) {
61 | int len = (int)Math.Min(length, buffer.Length);
62 | int read = stream.Read(buffer, 0, len);
63 | if (read == 0)
64 | throw new InvalidOperationException("Couldn't read all bytes");
65 | hasher.TransformBlock(buffer, 0, read, buffer, 0);
66 | length -= read;
67 | }
68 | hasher.TransformFinalBlock(Array2.Empty(), 0, 0);
69 | return hasher.Hash;
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/HeapBase.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using dnlib.IO;
4 | using dnlib.PE;
5 |
6 | namespace dnlib.DotNet.Writer {
7 | ///
8 | /// Base class of most heaps
9 | ///
10 | public abstract class HeapBase : IHeap {
11 | internal const uint ALIGNMENT = 4;
12 | FileOffset offset;
13 | RVA rva;
14 |
15 | ///
16 | /// true if has been called
17 | ///
18 | protected bool isReadOnly;
19 |
20 | ///
21 | public FileOffset FileOffset => offset;
22 |
23 | ///
24 | public RVA RVA => rva;
25 |
26 | ///
27 | public abstract string Name { get; }
28 |
29 | ///
30 | public bool IsEmpty => GetRawLength() <= 1;
31 |
32 | ///
33 | /// true if offsets require 4 bytes instead of 2 bytes.
34 | ///
35 | public bool IsBig => GetFileLength() > 0xFFFF;
36 |
37 | ///
38 | public void SetReadOnly() => isReadOnly = true;
39 |
40 | ///
41 | public virtual void SetOffset(FileOffset offset, RVA rva) {
42 | this.offset = offset;
43 | this.rva = rva;
44 |
45 | // NOTE: This method can be called twice by NativeModuleWriter, see Metadata.SetOffset() for more info
46 | }
47 |
48 | ///
49 | public uint GetFileLength() => Utils.AlignUp(GetRawLength(), ALIGNMENT);
50 |
51 | ///
52 | public uint GetVirtualSize() => GetFileLength();
53 |
54 | ///
55 | public uint CalculateAlignment() => 0;
56 |
57 | ///
58 | /// Gets the raw length of the heap
59 | ///
60 | /// Raw length of the heap
61 | public abstract uint GetRawLength();
62 |
63 | ///
64 | public void WriteTo(DataWriter writer) {
65 | WriteToImpl(writer);
66 | writer.WriteZeroes((int)(Utils.AlignUp(GetRawLength(), ALIGNMENT) - GetRawLength()));
67 | }
68 |
69 | ///
70 | /// Writes all data to at its current location.
71 | ///
72 | /// Destination
73 | protected abstract void WriteToImpl(DataWriter writer);
74 |
75 | ///
76 | public override string ToString() => Name;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/IHeap.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Writer {
4 | ///
5 | /// .NET Heap interface
6 | ///
7 | public interface IHeap : IChunk {
8 | ///
9 | /// Gets the name of the heap
10 | ///
11 | string Name { get; }
12 |
13 | ///
14 | /// Checks whether the heap is empty
15 | ///
16 | bool IsEmpty { get; }
17 |
18 | ///
19 | /// Called when the heap should be set to read-only mode
20 | ///
21 | void SetReadOnly();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/IOffsetHeap.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Collections.Generic;
4 |
5 | namespace dnlib.DotNet.Writer {
6 | ///
7 | /// Interface to get and set raw heap data. Implemented by the offset heaps: #Strings,
8 | /// #GUID, #Blob, and #US.
9 | ///
10 | /// Type of cooked data
11 | public interface IOffsetHeap {
12 | ///
13 | /// Gets the size of the data as raw data when written to the heap
14 | ///
15 | /// The data
16 | /// Size of the data as raw data when written to the heap
17 | int GetRawDataSize(TValue data);
18 |
19 | ///
20 | /// Overrides what value should be written to the heap.
21 | ///
22 | /// Offset of value. Must match an offset returned by
23 | ///
24 | /// The new raw data. The size must match the raw size exactly.
25 | void SetRawData(uint offset, byte[] rawData);
26 |
27 | ///
28 | /// Gets all inserted raw data and their offsets. The returned array
29 | /// is owned by the caller.
30 | ///
31 | /// An enumerable of all raw data and their offsets
32 | IEnumerable> GetAllRawData();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/IWriterError.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Writer {
4 | ///
5 | /// Gets notified of errors. The default handler should normally throw since the written data
6 | /// will probably be invalid. Any error can be ignored.
7 | ///
8 | public interface IWriterError {
9 | ///
10 | /// Called when an error is detected (eg. a null pointer or other invalid value). The error
11 | /// can be ignored but the written data won't be valid.
12 | ///
13 | /// Error message
14 | void Error(string message);
15 | }
16 |
17 | ///
18 | /// Gets notified of errors. The default handler should normally throw since the written data
19 | /// will probably be invalid. Any error can be ignored.
20 | ///
21 | public interface IWriterError2 : IWriterError {
22 | ///
23 | /// Called when an error is detected (eg. a null pointer or other invalid value). The error
24 | /// can be ignored but the written data won't be valid.
25 | ///
26 | /// Error message
27 | /// Optional message arguments
28 | void Error(string message, params object[] args);
29 | }
30 |
31 | static partial class Extensions {
32 | ///
33 | /// Called when an error is detected (eg. a null pointer or other invalid value). The error
34 | /// can be ignored but the written data won't be valid.
35 | ///
36 | /// The instance of
37 | /// Error message
38 | /// Optional message arguments
39 | internal static void Error2(this IWriterError helper, string message, params object[] args) {
40 | if (helper is IWriterError2 helper2)
41 | helper2.Error(message, args);
42 | else
43 | helper.Error(string.Format(message, args));
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/ImportAddressTable.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using dnlib.IO;
4 | using dnlib.PE;
5 |
6 | namespace dnlib.DotNet.Writer {
7 | ///
8 | /// Import address table chunk
9 | ///
10 | public sealed class ImportAddressTable : IChunk {
11 | readonly bool is64bit;
12 | FileOffset offset;
13 | RVA rva;
14 |
15 | ///
16 | /// Gets/sets the
17 | ///
18 | public ImportDirectory ImportDirectory { get; set; }
19 |
20 | ///
21 | public FileOffset FileOffset => offset;
22 |
23 | ///
24 | public RVA RVA => rva;
25 |
26 | internal bool Enable { get; set; }
27 |
28 | ///
29 | /// Constructor
30 | ///
31 | /// true if it's a 64-bit PE file, false if it's a 32-bit PE file
32 | public ImportAddressTable(bool is64bit) => this.is64bit = is64bit;
33 |
34 | ///
35 | public void SetOffset(FileOffset offset, RVA rva) {
36 | this.offset = offset;
37 | this.rva = rva;
38 | }
39 |
40 | ///
41 | public uint GetFileLength() {
42 | if (!Enable)
43 | return 0;
44 | return is64bit ? 16U : 8;
45 | }
46 |
47 | ///
48 | public uint GetVirtualSize() => GetFileLength();
49 |
50 | ///
51 | public uint CalculateAlignment() => 0;
52 |
53 | ///
54 | public void WriteTo(DataWriter writer) {
55 | if (!Enable)
56 | return;
57 | if (is64bit) {
58 | writer.WriteUInt64((ulong)(uint)ImportDirectory.CorXxxMainRVA);
59 | writer.WriteUInt64(0);
60 | }
61 | else {
62 | writer.WriteUInt32((uint)ImportDirectory.CorXxxMainRVA);
63 | writer.WriteInt32(0);
64 | }
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/MetadataErrorContext.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Text;
5 |
6 | namespace dnlib.DotNet.Writer {
7 | sealed class MetadataErrorContext {
8 | sealed class ErrorSource : IDisposable {
9 | MetadataErrorContext context;
10 | readonly ErrorSource originalValue;
11 |
12 | public object Value { get; }
13 |
14 | public ErrorSource(MetadataErrorContext context, object value) {
15 | this.context = context;
16 | Value = value;
17 | originalValue = context.source;
18 | }
19 |
20 | public void Dispose() {
21 | if (context is null)
22 | return;
23 | context.source = originalValue;
24 | context = null;
25 | }
26 | }
27 |
28 | ErrorSource source;
29 |
30 | public MetadataEvent Event { get; set; }
31 |
32 | public IDisposable SetSource(object source) => this.source = new ErrorSource(this, source);
33 |
34 | public void Append(string errorLevel, ref string message, ref object[] args) {
35 | int count = 1;
36 | var stringSource = source?.Value as string;
37 | var tokenSource = source?.Value as IMDTokenProvider;
38 | if (tokenSource is not null)
39 | count += 2;
40 | int ctxArgIndex = args.Length;
41 |
42 | var newMessage = new StringBuilder(message);
43 | var newArgs = new object[args.Length + count];
44 | Array.Copy(args, 0, newArgs, 0, args.Length);
45 |
46 | if (newMessage.Length != 0 && newMessage[newMessage.Length - 1] != '.')
47 | newMessage.Append('.');
48 | newMessage.AppendFormat(" {0} occurred after metadata event {{{1}}}", errorLevel, ctxArgIndex);
49 | newArgs[ctxArgIndex] = Event;
50 |
51 | if (tokenSource is not null) {
52 | string sourceType = tokenSource switch {
53 | TypeDef => "type",
54 | FieldDef => "field",
55 | MethodDef => "method",
56 | EventDef => "event",
57 | PropertyDef => "property",
58 | _ => "???"
59 | };
60 | newMessage.AppendFormat(" during writing {0} '{{{1}}}' (0x{{{2}:X8}})", sourceType, ctxArgIndex + 1, ctxArgIndex + 2);
61 | newArgs[ctxArgIndex + 1] = tokenSource;
62 | newArgs[ctxArgIndex + 2] = tokenSource.MDToken.Raw;
63 | }
64 | else if (stringSource is not null) {
65 | newMessage.AppendFormat(" during writing {0}", stringSource);
66 | }
67 |
68 | message = newMessage.Append('.').ToString();
69 | args = newArgs;
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/MetadataEvent.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Writer {
4 | ///
5 | /// All events
6 | ///
7 | public enum MetadataEvent {
8 | ///
9 | /// Creating the tables has just begun
10 | ///
11 | BeginCreateTables,
12 |
13 | ///
14 | /// Before allocating all TypeDef RIDs
15 | ///
16 | AllocateTypeDefRids,
17 |
18 | ///
19 | /// Before allocating all MemberDef RIDs
20 | ///
21 | AllocateMemberDefRids,
22 |
23 | ///
24 | /// The rids of types, fields, methods, events, properties and parameters are
25 | /// now known.
26 | ///
27 | MemberDefRidsAllocated,
28 |
29 | ///
30 | /// The tables and rows of all types, fields, methods, events, properties and parameters
31 | /// have been initialized. Method body RVAs are still not known, and no method has been
32 | /// written yet.
33 | ///
34 | MemberDefsInitialized,
35 |
36 | ///
37 | /// Before sorting most tables
38 | ///
39 | BeforeSortTables,
40 |
41 | ///
42 | /// Most of the tables that should be sorted have been sorted. The CustomAttribute
43 | /// table is still unsorted since it hasn't been created yet.
44 | ///
45 | MostTablesSorted,
46 |
47 | ///
48 | /// Custom attributes of all types, fields, methods, events, properties and parameters
49 | /// have now been written.
50 | ///
51 | MemberDefCustomAttributesWritten,
52 |
53 | ///
54 | /// All resources are about to be added to the .NET resources table
55 | ///
56 | BeginAddResources,
57 |
58 | ///
59 | /// All resources have been added to the .NET resources table
60 | ///
61 | EndAddResources,
62 |
63 | ///
64 | /// All method bodies are about to be written
65 | ///
66 | BeginWriteMethodBodies,
67 |
68 | ///
69 | /// All method bodies have been written. Their RVAs are still not known.
70 | ///
71 | EndWriteMethodBodies,
72 |
73 | ///
74 | /// All tables are now sorted, including the CustomAttribute table.
75 | ///
76 | OnAllTablesSorted,
77 |
78 | ///
79 | /// All tables have been created and all rows populated. The only columns that haven't
80 | /// been initialized yet are the ones that are RVAs.
81 | ///
82 | EndCreateTables,
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/ModuleWriterException.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Runtime.Serialization;
5 |
6 | namespace dnlib.DotNet.Writer {
7 | ///
8 | /// Thrown when the module writer encounters an unrecoverable error
9 | ///
10 | [Serializable]
11 | public class ModuleWriterException : Exception {
12 | ///
13 | /// Default constructor
14 | ///
15 | public ModuleWriterException() {
16 | }
17 |
18 | ///
19 | /// Constructor
20 | ///
21 | /// Error message
22 | public ModuleWriterException(string message)
23 | : base(message) {
24 | }
25 |
26 | ///
27 | /// Constructor
28 | ///
29 | /// Error message
30 | /// Other exception
31 | public ModuleWriterException(string message, Exception innerException)
32 | : base(message, innerException) {
33 | }
34 |
35 | ///
36 | /// Constructor
37 | ///
38 | ///
39 | ///
40 | protected ModuleWriterException(SerializationInfo info, StreamingContext context)
41 | : base(info, context) {
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/PortablePdbConstants.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Writer {
4 | static class PortablePdbConstants {
5 | // See System.Reflection.Metadata.PortablePdbVersions
6 |
7 | // Portable PDB version (v1.0)
8 | // Format version is stored in DebugDirectory.MajorVersion
9 | // SRM: DefaultFormatVersion, MinFormatVersion
10 | public const ushort FormatVersion = 0x0100;
11 |
12 | // Embedded Portable PDB Blob verison (v1.0)
13 | // Embedded version is stored in DebugDirectory.MinorVersion
14 | // SRM: MinEmbeddedVersion, DefaultEmbeddedVersion, MinUnsupportedEmbeddedVersion
15 | public const ushort EmbeddedVersion = 0x0100;
16 |
17 | // Stored in DebugDirectory.MinorVersion and indicates that it's a portable PDB file
18 | // and not a Windows PDB file
19 | public const ushort PortableCodeViewVersionMagic = 0x504D;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/RoslynContentIdProvider.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.DotNet.Writer {
6 | static class RoslynContentIdProvider {
7 | public static void GetContentId(byte[] hash, out Guid guid, out uint timestamp) {
8 | if (hash.Length < 20)
9 | throw new InvalidOperationException();
10 | var guidBytes = new byte[16];
11 | Array.Copy(hash, 0, guidBytes, 0, guidBytes.Length);
12 | guidBytes[7] = (byte)((guidBytes[7] & 0x0F) | 0x40);
13 | guidBytes[8] = (byte)((guidBytes[8] & 0x3F) | 0x80);
14 | guid = new Guid(guidBytes);
15 | timestamp = 0x80000000 | (uint)((hash[19] << 24) | (hash[18] << 16) | (hash[17] << 8) | hash[16]);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/SectionSizes.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Collections.Generic;
5 |
6 | namespace dnlib.DotNet.Writer {
7 | readonly struct SectionSizeInfo {
8 | ///
9 | /// Length of section
10 | ///
11 | public readonly uint length;
12 |
13 | ///
14 | /// Section characteristics
15 | ///
16 | public readonly uint characteristics;
17 |
18 | ///
19 | /// Constructor
20 | ///
21 | /// Length of section
22 | /// Section characteristics
23 | public SectionSizeInfo(uint length, uint characteristics) {
24 | this.length = length;
25 | this.characteristics = characteristics;
26 | }
27 | }
28 |
29 | ///
30 | /// Calculates the optional header section sizes
31 | ///
32 | readonly struct SectionSizes {
33 | public readonly uint SizeOfHeaders;
34 | public readonly uint SizeOfImage;
35 | public readonly uint BaseOfData, BaseOfCode;
36 | public readonly uint SizeOfCode, SizeOfInitdData, SizeOfUninitdData;
37 |
38 | public static uint GetSizeOfHeaders(uint fileAlignment, uint headerLen) => Utils.AlignUp(headerLen, fileAlignment);
39 |
40 | public SectionSizes(uint fileAlignment, uint sectionAlignment, uint headerLen, Func> getSectionSizeInfos) {
41 | SizeOfHeaders = GetSizeOfHeaders(fileAlignment, headerLen);
42 | SizeOfImage = Utils.AlignUp(SizeOfHeaders, sectionAlignment);
43 | BaseOfData = 0;
44 | BaseOfCode = 0;
45 | SizeOfCode = 0;
46 | SizeOfInitdData = 0;
47 | SizeOfUninitdData = 0;
48 | foreach (var section in getSectionSizeInfos()) {
49 | uint sectAlignedVs = Utils.AlignUp(section.length, sectionAlignment);
50 | uint fileAlignedVs = Utils.AlignUp(section.length, fileAlignment);
51 |
52 | bool isCode = (section.characteristics & 0x20) != 0;
53 | bool isInitdData = (section.characteristics & 0x40) != 0;
54 | bool isUnInitdData = (section.characteristics & 0x80) != 0;
55 |
56 | if (BaseOfCode == 0 && isCode)
57 | BaseOfCode = SizeOfImage;
58 | if (BaseOfData == 0 && (isInitdData || isUnInitdData))
59 | BaseOfData = SizeOfImage;
60 | if (isCode)
61 | SizeOfCode += fileAlignedVs;
62 | if (isInitdData)
63 | SizeOfInitdData += fileAlignedVs;
64 | if (isUnInitdData)
65 | SizeOfUninitdData += fileAlignedVs;
66 |
67 | SizeOfImage += sectAlignedVs;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/SerializerMethodContext.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using dnlib.DotNet.Emit;
6 |
7 | namespace dnlib.DotNet.Writer {
8 | sealed class SerializerMethodContext {
9 | readonly Dictionary toOffset;
10 | readonly IWriterError helper;
11 | MethodDef method;
12 | CilBody body;
13 | uint bodySize;
14 | bool dictInitd;
15 |
16 | public bool HasBody => body is not null;
17 |
18 | public SerializerMethodContext(IWriterError helper) {
19 | toOffset = new Dictionary();
20 | this.helper = helper;
21 | }
22 |
23 | internal void SetBody(MethodDef method) {
24 | if (this.method != method) {
25 | toOffset.Clear();
26 | this.method = method;
27 | body = method?.Body;
28 | dictInitd = false;
29 | }
30 | }
31 |
32 | public uint GetOffset(Instruction instr) {
33 | if (!dictInitd) {
34 | Debug.Assert(body is not null);
35 | if (body is null)
36 | return 0;
37 | InitializeDict();
38 | }
39 | if (instr is null)
40 | return bodySize;
41 | if (toOffset.TryGetValue(instr, out uint offset))
42 | return offset;
43 | helper.Error("Couldn't find an instruction, maybe it was removed. It's still being referenced by some code or by the PDB");
44 | return bodySize;
45 | }
46 |
47 | public bool IsSameMethod(MethodDef method) => this.method == method;
48 |
49 | void InitializeDict() {
50 | Debug.Assert(body is not null);
51 | Debug.Assert(toOffset.Count == 0);
52 | uint offset = 0;
53 | var instrs = body.Instructions;
54 | for(int i = 0; i < instrs.Count; i++) {
55 | var instr = instrs[i];
56 | toOffset[instr] = offset;
57 | offset += (uint)instr.GetSize();
58 | }
59 | bodySize = offset;
60 | dictInitd = true;
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/StrongNameSignature.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using dnlib.IO;
4 | using dnlib.PE;
5 |
6 | namespace dnlib.DotNet.Writer {
7 | ///
8 | /// Strong name signature chunk
9 | ///
10 | public sealed class StrongNameSignature : IReuseChunk {
11 | FileOffset offset;
12 | RVA rva;
13 | int size;
14 |
15 | ///
16 | public FileOffset FileOffset => offset;
17 |
18 | ///
19 | public RVA RVA => rva;
20 |
21 | ///
22 | /// Constructor
23 | ///
24 | /// Size of strong name signature
25 | public StrongNameSignature(int size) => this.size = size;
26 |
27 | bool IReuseChunk.CanReuse(RVA origRva, uint origSize) => (uint)size <= origSize;
28 |
29 | ///
30 | public void SetOffset(FileOffset offset, RVA rva) {
31 | this.offset = offset;
32 | this.rva = rva;
33 | }
34 |
35 | ///
36 | public uint GetFileLength() => (uint)size;
37 |
38 | ///
39 | public uint GetVirtualSize() => GetFileLength();
40 |
41 | ///
42 | public uint CalculateAlignment() => 0;
43 |
44 | ///
45 | public void WriteTo(DataWriter writer) => writer.WriteZeroes(size);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/DotNet/Writer/WriterUtils.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.DotNet.Writer {
4 | static class WriterUtils {
5 | public static uint WriteCompressedUInt32(this DataWriter writer, IWriterError helper, uint value) {
6 | if (value > 0x1FFFFFFF) {
7 | helper.Error("UInt32 value is too big and can't be compressed");
8 | value = 0x1FFFFFFF;
9 | }
10 | writer.WriteCompressedUInt32(value);
11 | return value;
12 | }
13 |
14 | public static int WriteCompressedInt32(this DataWriter writer, IWriterError helper, int value) {
15 | if (value < -0x10000000) {
16 | helper.Error("Int32 value is too small and can't be compressed.");
17 | value = -0x10000000;
18 | }
19 | else if (value > 0x0FFFFFFF) {
20 | helper.Error("Int32 value is too big and can't be compressed.");
21 | value = 0x0FFFFFFF;
22 | }
23 | writer.WriteCompressedInt32(value);
24 | return value;
25 | }
26 |
27 | public static void Write(this DataWriter writer, IWriterError helper, UTF8String s) {
28 | if (UTF8String.IsNull(s)) {
29 | helper.Error("UTF8String is null");
30 | s = UTF8String.Empty;
31 | }
32 |
33 | writer.WriteCompressedUInt32(helper, (uint)s.DataLength);
34 | writer.WriteBytes(s.Data);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/HandleProcessCorruptedStateExceptionsAttribute.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | #if NET35
4 | namespace System.Runtime.ExceptionServices {
5 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
6 | sealed class HandleProcessCorruptedStateExceptionsAttribute : Attribute {
7 | }
8 | }
9 | #endif
10 |
--------------------------------------------------------------------------------
/src/IO/ByteArrayDataReaderFactory.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.IO {
6 | ///
7 | /// A that reads from a byte array
8 | ///
9 | public sealed class ByteArrayDataReaderFactory : DataReaderFactory {
10 | ///
11 | /// The filename or null if the data is not from a file
12 | ///
13 | public override string Filename => filename;
14 |
15 | ///
16 | /// Gets the total length of the data
17 | ///
18 | public override uint Length => length;
19 |
20 | internal byte[] DataArray => data;
21 | internal uint DataOffset => 0;
22 |
23 | DataStream stream;
24 | string filename;
25 | uint length;
26 | byte[] data;
27 |
28 | ByteArrayDataReaderFactory(byte[] data, string filename) {
29 | this.filename = filename;
30 | length = (uint)data.Length;
31 | stream = DataStreamFactory.Create(data);
32 | this.data = data;
33 | }
34 |
35 | ///
36 | /// Creates a instance
37 | ///
38 | /// Data
39 | /// The filename or null if the data is not from a file
40 | ///
41 | public static ByteArrayDataReaderFactory Create(byte[] data, string filename) {
42 | if (data is null)
43 | throw new ArgumentNullException(nameof(data));
44 | return new ByteArrayDataReaderFactory(data, filename);
45 | }
46 |
47 | ///
48 | /// Creates a data reader
49 | ///
50 | /// Data
51 | ///
52 | public static DataReader CreateReader(byte[] data) => Create(data, filename: null).CreateReader();
53 |
54 | ///
55 | /// Creates a data reader
56 | ///
57 | /// Offset of data
58 | /// Length of data
59 | ///
60 | public override DataReader CreateReader(uint offset, uint length) => CreateReader(stream, offset, length);
61 |
62 | ///
63 | /// This method doesn't need to be called since a has nothing that must be cleaned up
64 | ///
65 | public override void Dispose() {
66 | stream = EmptyDataStream.Instance;
67 | length = 0;
68 | filename = null;
69 | data = null;
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/IO/DataReaderFactoryFactory.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.IO;
5 | using System.Runtime.InteropServices;
6 |
7 | namespace dnlib.IO {
8 | static class DataReaderFactoryFactory {
9 | static readonly bool isUnix;
10 |
11 | static DataReaderFactoryFactory() {
12 | // See http://mono-project.com/FAQ:_Technical#Mono_Platforms for platform detection.
13 | int p = (int)Environment.OSVersion.Platform;
14 | if (p == 4 || p == 6 || p == 128)
15 | isUnix = true;
16 | #if NETSTANDARD || NETCOREAPP
17 | if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
18 | isUnix = true;
19 | #endif
20 | }
21 |
22 | public static DataReaderFactory Create(string fileName, bool mapAsImage) {
23 | var creator = CreateDataReaderFactory(fileName, mapAsImage);
24 | if (creator is not null)
25 | return creator;
26 |
27 | return ByteArrayDataReaderFactory.Create(File.ReadAllBytes(fileName), fileName);
28 | }
29 |
30 | static DataReaderFactory CreateDataReaderFactory(string fileName, bool mapAsImage) {
31 | if (!isUnix)
32 | return MemoryMappedDataReaderFactory.CreateWindows(fileName, mapAsImage);
33 | else
34 | return MemoryMappedDataReaderFactory.CreateUnix(fileName, mapAsImage);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/IO/DataReaderStream.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.IO;
5 |
6 | namespace dnlib.IO {
7 | sealed class DataReaderStream : Stream {
8 | public override bool CanRead => true;
9 | public override bool CanSeek => true;
10 | public override bool CanWrite => false;
11 | public override long Length => reader.Length;
12 |
13 | public override long Position {
14 | get => position;
15 | set => position = value;
16 | }
17 |
18 | DataReader reader;
19 | long position;
20 |
21 | public DataReaderStream(in DataReader reader) {
22 | this.reader = reader;
23 | position = reader.Position;
24 | }
25 |
26 | public override void Flush() { }
27 |
28 | bool CheckAndSetPosition() {
29 | if ((ulong)position > reader.Length)
30 | return false;
31 | reader.Position = (uint)position;
32 | return true;
33 | }
34 |
35 | public override long Seek(long offset, SeekOrigin origin) {
36 | switch (origin) {
37 | case SeekOrigin.Begin: Position = offset; break;
38 | case SeekOrigin.Current: Position += offset; break;
39 | case SeekOrigin.End: Position = Length + offset; break;
40 | }
41 | return Position;
42 | }
43 |
44 | public override int Read(byte[] buffer, int offset, int count) {
45 | if (buffer is null)
46 | throw new ArgumentNullException(nameof(buffer));
47 | if (offset < 0)
48 | throw new ArgumentOutOfRangeException(nameof(offset));
49 | if (count < 0)
50 | throw new ArgumentOutOfRangeException(nameof(count));
51 | if (!CheckAndSetPosition())
52 | return 0;
53 | int bytesToRead = (int)Math.Min((uint)count, reader.BytesLeft);
54 | reader.ReadBytes(buffer, offset, bytesToRead);
55 | Position += bytesToRead;
56 | return bytesToRead;
57 | }
58 |
59 | public override int ReadByte() {
60 | if (!CheckAndSetPosition() || !reader.CanRead(1U))
61 | return -1;
62 | Position++;
63 | return reader.ReadByte();
64 | }
65 |
66 | public override void SetLength(long value) => throw new NotSupportedException();
67 | public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/IO/DataStreamFactory.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Diagnostics;
5 | using dnlib.PE;
6 |
7 | namespace dnlib.IO {
8 | ///
9 | /// Creates s
10 | ///
11 | public static unsafe class DataStreamFactory {
12 | //TODO: There are other places that use pointers that also need to be updated
13 | static bool supportsUnalignedAccesses = CalculateSupportsUnalignedAccesses();
14 |
15 | static bool CalculateSupportsUnalignedAccesses() {
16 | var machine = ProcessorArchUtils.GetProcessCpuArchitecture();
17 | switch (machine) {
18 | case Machine.I386:
19 | case Machine.AMD64:
20 | return true;
21 | case Machine.ARMNT:
22 | case Machine.ARM64:
23 | return false;
24 | default:
25 | Debug.Fail($"Unknown CPU arch: {machine}");
26 | return true;
27 | }
28 | }
29 |
30 | ///
31 | /// Creates a that reads from native memory
32 | ///
33 | /// Pointer to data
34 | ///
35 | public static DataStream Create(byte* data) {
36 | if (data is null)
37 | throw new ArgumentNullException(nameof(data));
38 | if (supportsUnalignedAccesses)
39 | return new UnalignedNativeMemoryDataStream(data);
40 | return new AlignedNativeMemoryDataStream(data);
41 | }
42 |
43 | ///
44 | /// Creates a that reads from a byte array
45 | ///
46 | /// Data
47 | ///
48 | public static DataStream Create(byte[] data) {
49 | if (data is null)
50 | throw new ArgumentNullException(nameof(data));
51 | if (supportsUnalignedAccesses)
52 | return new UnalignedByteArrayDataStream(data);
53 | return new AlignedByteArrayDataStream(data);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/IO/EmptyDataStream.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Text;
4 |
5 | namespace dnlib.IO {
6 | sealed unsafe class EmptyDataStream : DataStream {
7 | public static readonly DataStream Instance = new EmptyDataStream();
8 |
9 | EmptyDataStream() { }
10 |
11 | public override void ReadBytes(uint offset, void* destination, int length) {
12 | var p = (byte*)destination;
13 | for (int i = 0; i < length; i++)
14 | *p = 0;
15 | }
16 | public override void ReadBytes(uint offset, byte[] destination, int destinationIndex, int length) {
17 | for (int i = 0; i < length; i++)
18 | destination[destinationIndex + i] = 0;
19 | }
20 | public override byte ReadByte(uint offset) => 0;
21 | public override ushort ReadUInt16(uint offset) => 0;
22 | public override uint ReadUInt32(uint offset) => 0;
23 | public override ulong ReadUInt64(uint offset) => 0;
24 | public override float ReadSingle(uint offset) => 0;
25 | public override double ReadDouble(uint offset) => 0;
26 | public override string ReadUtf16String(uint offset, int chars) => string.Empty;
27 | public override string ReadString(uint offset, int length, Encoding encoding) => string.Empty;
28 | public override bool TryGetOffsetOf(uint offset, uint endOffset, byte value, out uint valueOffset) {
29 | valueOffset = 0;
30 | return false;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/IO/FileOffset.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.IO {
4 | ///
5 | /// Represents a file offset
6 | ///
7 | public enum FileOffset : uint {
8 | }
9 |
10 | partial class IOExtensions {
11 | ///
12 | /// Align up
13 | ///
14 | /// this
15 | /// Alignment
16 | public static FileOffset AlignUp(this FileOffset offset, uint alignment) => (FileOffset)(((uint)offset + alignment - 1) & ~(alignment - 1));
17 |
18 | ///
19 | /// Align up
20 | ///
21 | /// this
22 | /// Alignment
23 | public static FileOffset AlignUp(this FileOffset offset, int alignment) => (FileOffset)(((uint)offset + alignment - 1) & ~(alignment - 1));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/IO/FileSection.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Diagnostics;
4 |
5 | namespace dnlib.IO {
6 | ///
7 | /// Base class for classes needing to implement IFileSection
8 | ///
9 | [DebuggerDisplay("O:{startOffset} L:{size} {GetType().Name}")]
10 | public class FileSection : IFileSection {
11 | ///
12 | /// The start file offset of this section
13 | ///
14 | protected FileOffset startOffset;
15 |
16 | ///
17 | /// Size of the section
18 | ///
19 | protected uint size;
20 |
21 | ///
22 | public FileOffset StartOffset => startOffset;
23 |
24 | ///
25 | public FileOffset EndOffset => startOffset + size;
26 |
27 | ///
28 | /// Set to 's current position
29 | ///
30 | /// The reader
31 | protected void SetStartOffset(ref DataReader reader) =>
32 | startOffset = (FileOffset)reader.CurrentOffset;
33 |
34 | ///
35 | /// Set according to 's current position
36 | ///
37 | /// The reader
38 | protected void SetEndoffset(ref DataReader reader) =>
39 | size = reader.CurrentOffset - (uint)startOffset;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/IO/IFileSection.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.IO {
4 | ///
5 | /// Represents a section in a file
6 | ///
7 | public interface IFileSection {
8 | ///
9 | /// Start offset of the section in the file
10 | ///
11 | FileOffset StartOffset { get; }
12 |
13 | ///
14 | /// End offset of the section in the file. This is one byte after the last
15 | /// valid offset in the section.
16 | ///
17 | FileOffset EndOffset { get; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/IO/IOExtensions.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.IO {
4 | ///
5 | /// Extension methods
6 | ///
7 | public static partial class IOExtensions {
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/IO/NativeMemoryDataReaderFactory.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.IO {
6 | ///
7 | /// Creates s that read native memory
8 | ///
9 | public sealed unsafe class NativeMemoryDataReaderFactory : DataReaderFactory {
10 | ///
11 | /// The filename or null if the data is not from a file
12 | ///
13 | public override string Filename => filename;
14 |
15 | ///
16 | /// Gets the total length of the data
17 | ///
18 | public override uint Length => length;
19 |
20 | DataStream stream;
21 | string filename;
22 | uint length;
23 |
24 | NativeMemoryDataReaderFactory(byte* data, uint length, string filename) {
25 | this.filename = filename;
26 | this.length = length;
27 | stream = DataStreamFactory.Create(data);
28 | }
29 |
30 | internal void SetLength(uint length) => this.length = length;
31 |
32 | ///
33 | /// Creates a instance
34 | ///
35 | /// Pointer to data
36 | /// Length of data
37 | /// The filename or null if the data is not from a file
38 | ///
39 | public static NativeMemoryDataReaderFactory Create(byte* data, uint length, string filename) {
40 | if (data is null)
41 | throw new ArgumentNullException(nameof(data));
42 | return new NativeMemoryDataReaderFactory(data, length, filename);
43 | }
44 |
45 | ///
46 | /// Creates a data reader
47 | ///
48 | /// Offset of data
49 | /// Length of data
50 | ///
51 | public override DataReader CreateReader(uint offset, uint length) => CreateReader(stream, offset, length);
52 |
53 | ///
54 | /// This method doesn't need to be called since this instance doesn't own the native memory
55 | ///
56 | public override void Dispose() {
57 | stream = EmptyDataStream.Instance;
58 | length = 0;
59 | filename = null;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/PE/Characteristics.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.PE {
6 | ///
7 | /// IMAGE_FILE_HEADER.Characteristics flags
8 | ///
9 | [Flags]
10 | public enum Characteristics : ushort {
11 | /// Relocation info stripped from file.
12 | RelocsStripped = 0x0001,
13 | /// File is executable (i.e. no unresolved externel references).
14 | ExecutableImage = 0x0002,
15 | /// Line nunbers stripped from file.
16 | LineNumsStripped = 0x0004,
17 | /// Local symbols stripped from file.
18 | LocalSymsStripped = 0x0008,
19 | /// Agressively trim working set
20 | AggressiveWsTrim = 0x0010,
21 | /// App can handle >2gb addresses
22 | LargeAddressAware = 0x0020,
23 | ///
24 | Reserved1 = 0x0040,
25 | /// Bytes of machine word are reversed.
26 | BytesReversedLo = 0x0080,
27 | /// 32 bit word machine.
28 | Bit32Machine = 0x0100,
29 | /// Debugging info stripped from file in .DBG file
30 | DebugStripped = 0x0200,
31 | /// If Image is on removable media, copy and run from the swap file.
32 | RemovableRunFromSwap= 0x0400,
33 | /// If Image is on Net, copy and run from the swap file.
34 | NetRunFromSwap = 0x0800,
35 | /// System File.
36 | System = 0x1000,
37 | /// File is a DLL.
38 | Dll = 0x2000,
39 | /// File should only be run on a UP machine
40 | UpSystemOnly = 0x4000,
41 | /// Bytes of machine word are reversed.
42 | BytesReversedHi = 0x8000,
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/PE/DllCharacteristics.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.PE {
6 | ///
7 | /// IMAGE_OPTIONAL_HEADER.DllCharacteristics
8 | ///
9 | [Flags]
10 | public enum DllCharacteristics : ushort {
11 | ///
12 | Reserved1 = 0x0001,
13 | ///
14 | Reserved2 = 0x0002,
15 | ///
16 | Reserved3 = 0x0004,
17 | ///
18 | Reserved4 = 0x0008,
19 | ///
20 | Reserved5 = 0x0010,
21 | /// Image can handle a high entropy 64-bit virtual address space.
22 | HighEntropyVA = 0x0020,
23 | /// DLL can move.
24 | DynamicBase = 0x0040,
25 | /// Code Integrity Image
26 | ForceIntegrity = 0x0080,
27 | /// Image is NX compatible
28 | NxCompat = 0x0100,
29 | /// Image understands isolation and doesn't want it
30 | NoIsolation = 0x0200,
31 | /// Image does not use SEH. No SE handler may reside in this image
32 | NoSeh = 0x0400,
33 | /// Do not bind this image.
34 | NoBind = 0x0800,
35 | /// Image should execute in an AppContainer
36 | AppContainer = 0x1000,
37 | /// Driver uses WDM model
38 | WdmDriver = 0x2000,
39 | /// Image supports Control Flow Guard.
40 | GuardCf = 0x4000,
41 | ///
42 | TerminalServerAware = 0x8000,
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/PE/IPEType.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using dnlib.IO;
4 |
5 | namespace dnlib.PE {
6 | ///
7 | /// Converts a to/from an
8 | ///
9 | interface IPEType {
10 | ///
11 | /// Converts a to an , returns 0 if out of range
12 | ///
13 | /// The PEInfo context
14 | /// The file offset to convert
15 | /// The RVA
16 | RVA ToRVA(PEInfo peInfo, FileOffset offset);
17 |
18 | ///
19 | /// Converts an to a , returns 0 if out of range
20 | ///
21 | /// The PEInfo context
22 | /// The RVA to convert
23 | /// The file offset
24 | FileOffset ToFileOffset(PEInfo peInfo, RVA rva);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/PE/ImageDataDirectory.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Diagnostics;
5 | using dnlib.IO;
6 |
7 | namespace dnlib.PE {
8 | ///
9 | /// Represents the IMAGE_DATA_DIRECTORY PE section
10 | ///
11 | [DebuggerDisplay("{virtualAddress} {dataSize}")]
12 | public sealed class ImageDataDirectory : FileSection {
13 | readonly RVA virtualAddress;
14 | readonly uint dataSize;
15 |
16 | ///
17 | /// Returns the IMAGE_DATA_DIRECTORY.VirtualAddress field
18 | ///
19 | public RVA VirtualAddress => virtualAddress;
20 |
21 | ///
22 | /// Returns the IMAGE_DATA_DIRECTORY.Size field
23 | ///
24 | public uint Size => dataSize;
25 |
26 | ///
27 | /// Default constructor
28 | ///
29 | public ImageDataDirectory() {
30 | }
31 |
32 | ///
33 | /// Constructor
34 | ///
35 | /// PE file reader pointing to the start of this section
36 | /// Verify section
37 | /// Thrown if verification fails
38 | public ImageDataDirectory(ref DataReader reader, bool verify) {
39 | SetStartOffset(ref reader);
40 | virtualAddress = (RVA)reader.ReadUInt32();
41 | dataSize = reader.ReadUInt32();
42 | SetEndoffset(ref reader);
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/PE/ImageDebugDirectory.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Diagnostics;
5 | using dnlib.IO;
6 |
7 | namespace dnlib.PE {
8 | ///
9 | /// A IMAGE_DEBUG_DIRECTORY
10 | ///
11 | [DebuggerDisplay("{type}: TS:{timeDateStamp,h} V:{majorVersion,d}.{minorVersion,d} SZ:{sizeOfData} RVA:{addressOfRawData,h} FO:{pointerToRawData,h}")]
12 | public sealed class ImageDebugDirectory : FileSection {
13 | readonly uint characteristics;
14 | readonly uint timeDateStamp;
15 | readonly ushort majorVersion;
16 | readonly ushort minorVersion;
17 | readonly ImageDebugType type;
18 | readonly uint sizeOfData;
19 | readonly uint addressOfRawData;
20 | readonly uint pointerToRawData;
21 |
22 | ///
23 | /// Gets the characteristics (reserved)
24 | ///
25 | public uint Characteristics => characteristics;
26 |
27 | ///
28 | /// Gets the timestamp
29 | ///
30 | public uint TimeDateStamp => timeDateStamp;
31 |
32 | ///
33 | /// Gets the major version
34 | ///
35 | public ushort MajorVersion => majorVersion;
36 |
37 | ///
38 | /// Gets the minor version
39 | ///
40 | public ushort MinorVersion => minorVersion;
41 |
42 | ///
43 | /// Gets the type
44 | ///
45 | public ImageDebugType Type => type;
46 |
47 | ///
48 | /// Gets the size of data
49 | ///
50 | public uint SizeOfData => sizeOfData;
51 |
52 | ///
53 | /// RVA of the data
54 | ///
55 | public RVA AddressOfRawData => (RVA)addressOfRawData;
56 |
57 | ///
58 | /// File offset of the data
59 | ///
60 | public FileOffset PointerToRawData => (FileOffset)pointerToRawData;
61 |
62 | ///
63 | /// Constructor
64 | ///
65 | /// PE file reader pointing to the start of this section
66 | /// Verify section
67 | /// Thrown if verification fails
68 | public ImageDebugDirectory(ref DataReader reader, bool verify) {
69 | SetStartOffset(ref reader);
70 | characteristics = reader.ReadUInt32();
71 | timeDateStamp = reader.ReadUInt32();
72 | majorVersion = reader.ReadUInt16();
73 | minorVersion = reader.ReadUInt16();
74 | type = (ImageDebugType)reader.ReadUInt32();
75 | sizeOfData = reader.ReadUInt32();
76 | addressOfRawData = reader.ReadUInt32();
77 | pointerToRawData = reader.ReadUInt32();
78 | SetEndoffset(ref reader);
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/PE/ImageDebugType.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.PE {
4 | ///
5 | /// Image debug type, see IMAGE_DEBUG_TYPE_* in winnt.n
6 | ///
7 | public enum ImageDebugType : uint {
8 | #pragma warning disable 1591 // Missing XML comment for publicly visible type or member
9 | Unknown = 0,
10 | Coff = 1,
11 |
12 | ///
13 | /// Contains PDB info
14 | ///
15 | CodeView = 2,
16 |
17 | FPO = 3,
18 | Misc = 4,
19 | Exception = 5,
20 | Fixup = 6,
21 | OmapToSrc = 7,
22 | OmapFromSrc = 8,
23 | Borland = 9,
24 | Reserved10 = 10,
25 | CLSID = 11,
26 | VcFeature = 12,
27 | POGO = 13,
28 | ILTCG = 14,
29 | MPX = 15,
30 |
31 | ///
32 | /// It's a deterministic (reproducible) PE file
33 | ///
34 | Reproducible = 16,
35 |
36 | ///
37 | /// Embedded portable PDB data
38 | ///
39 | EmbeddedPortablePdb = 17,
40 |
41 | ///
42 | /// Checksum of the PDB file. 0 or more entries allowed.
43 | ///
44 | PdbChecksum = 19,
45 | #pragma warning restore 1591 // Missing XML comment for publicly visible type or member
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/PE/ImageDosHeader.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using dnlib.IO;
5 |
6 | namespace dnlib.PE {
7 | ///
8 | /// Represents the IMAGE_DOS_HEADER PE section
9 | ///
10 | public sealed class ImageDosHeader : FileSection {
11 | readonly uint ntHeadersOffset;
12 |
13 | ///
14 | /// File offset of the NT headers
15 | ///
16 | public uint NTHeadersOffset => ntHeadersOffset;
17 |
18 | ///
19 | /// Constructor
20 | ///
21 | /// PE file reader
22 | /// Verify section
23 | /// Thrown if verification fails
24 | public ImageDosHeader(ref DataReader reader, bool verify) {
25 | SetStartOffset(ref reader);
26 | ushort sig = reader.ReadUInt16();
27 | if (verify && sig != 0x5A4D)
28 | throw new BadImageFormatException("Invalid DOS signature");
29 | reader.Position = (uint)startOffset + 0x3C;
30 | ntHeadersOffset = reader.ReadUInt32();
31 | SetEndoffset(ref reader);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/PE/ImageFileHeader.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using dnlib.IO;
5 |
6 | namespace dnlib.PE {
7 | ///
8 | /// Represents the IMAGE_FILE_HEADER PE section
9 | ///
10 | public sealed class ImageFileHeader : FileSection {
11 | readonly Machine machine;
12 | readonly ushort numberOfSections;
13 | readonly uint timeDateStamp;
14 | readonly uint pointerToSymbolTable;
15 | readonly uint numberOfSymbols;
16 | readonly ushort sizeOfOptionalHeader;
17 | readonly Characteristics characteristics;
18 |
19 | ///
20 | /// Returns the IMAGE_FILE_HEADER.Machine field
21 | ///
22 | public Machine Machine => machine;
23 |
24 | ///
25 | /// Returns the IMAGE_FILE_HEADER.NumberOfSections field
26 | ///
27 | public int NumberOfSections => numberOfSections;
28 |
29 | ///
30 | /// Returns the IMAGE_FILE_HEADER.TimeDateStamp field
31 | ///
32 | public uint TimeDateStamp => timeDateStamp;
33 |
34 | ///
35 | /// Returns the IMAGE_FILE_HEADER.PointerToSymbolTable field
36 | ///
37 | public uint PointerToSymbolTable => pointerToSymbolTable;
38 |
39 | ///
40 | /// Returns the IMAGE_FILE_HEADER.NumberOfSymbols field
41 | ///
42 | public uint NumberOfSymbols => numberOfSymbols;
43 |
44 | ///
45 | /// Returns the IMAGE_FILE_HEADER.SizeOfOptionalHeader field
46 | ///
47 | public uint SizeOfOptionalHeader => sizeOfOptionalHeader;
48 |
49 | ///
50 | /// Returns the IMAGE_FILE_HEADER.Characteristics field
51 | ///
52 | public Characteristics Characteristics => characteristics;
53 |
54 | ///
55 | /// Constructor
56 | ///
57 | /// PE file reader pointing to the start of this section
58 | /// Verify section
59 | /// Thrown if verification fails
60 | public ImageFileHeader(ref DataReader reader, bool verify) {
61 | SetStartOffset(ref reader);
62 | machine = (Machine)reader.ReadUInt16();
63 | numberOfSections = reader.ReadUInt16();
64 | timeDateStamp = reader.ReadUInt32();
65 | pointerToSymbolTable = reader.ReadUInt32();
66 | numberOfSymbols = reader.ReadUInt32();
67 | sizeOfOptionalHeader = reader.ReadUInt16();
68 | characteristics = (Characteristics)reader.ReadUInt16();
69 | SetEndoffset(ref reader);
70 | if (verify && sizeOfOptionalHeader == 0)
71 | throw new BadImageFormatException("Invalid SizeOfOptionalHeader");
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/PE/ImageNTHeaders.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using dnlib.IO;
5 |
6 | namespace dnlib.PE {
7 | ///
8 | /// Represents the IMAGE_NT_HEADERS PE section
9 | ///
10 | public sealed class ImageNTHeaders : FileSection {
11 | readonly uint signature;
12 | readonly ImageFileHeader imageFileHeader;
13 | readonly IImageOptionalHeader imageOptionalHeader;
14 |
15 | ///
16 | /// Returns the IMAGE_NT_HEADERS.Signature field
17 | ///
18 | public uint Signature => signature;
19 |
20 | ///
21 | /// Returns the IMAGE_NT_HEADERS.FileHeader field
22 | ///
23 | public ImageFileHeader FileHeader => imageFileHeader;
24 |
25 | ///
26 | /// Returns the IMAGE_NT_HEADERS.OptionalHeader field
27 | ///
28 | public IImageOptionalHeader OptionalHeader => imageOptionalHeader;
29 |
30 | ///
31 | /// Constructor
32 | ///
33 | /// PE file reader pointing to the start of this section
34 | /// Verify section
35 | /// Thrown if verification fails
36 | public ImageNTHeaders(ref DataReader reader, bool verify) {
37 | SetStartOffset(ref reader);
38 | signature = reader.ReadUInt32();
39 | // Mono only checks the low 2 bytes
40 | if (verify && (ushort)signature != 0x4550)
41 | throw new BadImageFormatException("Invalid NT headers signature");
42 | imageFileHeader = new ImageFileHeader(ref reader, verify);
43 | imageOptionalHeader = CreateImageOptionalHeader(ref reader, verify);
44 | SetEndoffset(ref reader);
45 | }
46 |
47 | ///
48 | /// Creates an IImageOptionalHeader
49 | ///
50 | /// PE file reader pointing to the start of the optional header
51 | /// Verify section
52 | /// The created IImageOptionalHeader
53 | /// Thrown if verification fails
54 | IImageOptionalHeader CreateImageOptionalHeader(ref DataReader reader, bool verify) {
55 | ushort magic = reader.ReadUInt16();
56 | reader.Position -= 2;
57 | return magic switch {
58 | 0x010B => new ImageOptionalHeader32(ref reader, imageFileHeader.SizeOfOptionalHeader, verify),
59 | 0x020B => new ImageOptionalHeader64(ref reader, imageFileHeader.SizeOfOptionalHeader, verify),
60 | _ => throw new BadImageFormatException("Invalid optional header magic"),
61 | };
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/PE/PEExtensions.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.IO;
5 |
6 | namespace dnlib.PE {
7 | ///
8 | /// Extension methods
9 | ///
10 | public static partial class PEExtensions {
11 | ///
12 | /// Calculates a PE checksum
13 | ///
14 | /// PE image stream positioned at the MZ bytes
15 | /// Length of image
16 | /// Offset of checksum
17 | /// PE checksum
18 | internal static uint CalculatePECheckSum(this Stream stream, long length, long checkSumOffset) {
19 | if ((length & 1) != 0)
20 | ThrowInvalidOperationException("Invalid PE length");
21 | var buffer = new byte[(int)Math.Min(length, 0x2000)];
22 | uint checkSum = 0;
23 | checkSum = CalculatePECheckSum(stream, checkSumOffset, checkSum, buffer);
24 | const int ChecksumFieldSize = 4;
25 | stream.Position += ChecksumFieldSize;
26 | checkSum = CalculatePECheckSum(stream, length - checkSumOffset - ChecksumFieldSize, checkSum, buffer);
27 | ulong cks = (ulong)checkSum + (ulong)length;
28 | return (uint)cks + (uint)(cks >> 32);
29 | }
30 |
31 | static uint CalculatePECheckSum(Stream stream, long length, uint checkSum, byte[] buffer) {
32 | for (long offset = 0; offset < length;) {
33 | int len = (int)Math.Min(length - offset, buffer.Length);
34 | int count = stream.Read(buffer, 0, len);
35 | if (count != len)
36 | ThrowInvalidOperationException("Couldn't read all bytes");
37 |
38 | for (int i = 0; i < count;) {
39 | checkSum += buffer[i++] | ((uint)buffer[i++] << 8);
40 | checkSum = (ushort)(checkSum + (checkSum >> 16));
41 | }
42 |
43 | offset += count;
44 | }
45 | return checkSum;
46 | }
47 |
48 | static void ThrowInvalidOperationException(string message) => throw new InvalidOperationException(message);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/PE/RVA.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.PE {
4 | ///
5 | /// Represents an RVA (relative virtual address)
6 | ///
7 | public enum RVA : uint {
8 | }
9 |
10 | partial class PEExtensions {
11 | ///
12 | /// Align up
13 | ///
14 | /// this
15 | /// Alignment
16 | public static RVA AlignUp(this RVA rva, uint alignment) => (RVA)(((uint)rva + alignment - 1) & ~(alignment - 1));
17 |
18 | ///
19 | /// Align up
20 | ///
21 | /// this
22 | /// Alignment
23 | public static RVA AlignUp(this RVA rva, int alignment) => (RVA)(((uint)rva + alignment - 1) & ~(alignment - 1));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/PE/Subsystem.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.PE {
4 | ///
5 | /// IMAGE_OPTIONAL_HEADER.Subsystem
6 | ///
7 | public enum Subsystem : ushort {
8 | /// Unknown subsystem.
9 | Unknown = 0,
10 | /// Image doesn't require a subsystem.
11 | Native = 1,
12 | /// Image runs in the Windows GUI subsystem.
13 | WindowsGui = 2,
14 | /// Image runs in the Windows character subsystem.
15 | WindowsCui = 3,
16 | /// image runs in the OS/2 character subsystem.
17 | Os2Cui = 5,
18 | /// image runs in the Posix character subsystem.
19 | PosixCui = 7,
20 | /// image is a native Win9x driver.
21 | NativeWindows = 8,
22 | /// Image runs in the Windows CE subsystem.
23 | WindowsCeGui = 9,
24 | ///
25 | EfiApplication = 10,
26 | ///
27 | EfiBootServiceDriver = 11,
28 | ///
29 | EfiRuntimeDriver = 12,
30 | ///
31 | EfiRom = 13,
32 | ///
33 | Xbox = 14,
34 | ///
35 | WindowsBootApplication = 16,
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Settings.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib {
4 | ///
5 | /// dnlib settings
6 | ///
7 | public static class Settings {
8 | ///
9 | /// true if dnlib is thread safe. (THREAD_SAFE was defined during compilation)
10 | ///
11 | public static bool IsThreadSafe {
12 | get {
13 | #if THREAD_SAFE
14 | return true;
15 | #else
16 | return false;
17 | #endif
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Threading/ICancellationToken.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 |
5 | namespace dnlib.Threading {
6 | ///
7 | /// Cancellation token interface
8 | ///
9 | public interface ICancellationToken {
10 | ///
11 | /// Throws a if the operation should be canceled
12 | ///
13 | void ThrowIfCancellationRequested();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Threading/Lock.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Runtime.Serialization;
5 | using System.Threading;
6 |
7 | namespace dnlib.Threading {
8 | #if THREAD_SAFE
9 | [Serializable]
10 | class LockException : Exception {
11 | public LockException() {
12 | }
13 |
14 | public LockException(string msg)
15 | : base(msg) {
16 | }
17 |
18 | protected LockException(SerializationInfo info, StreamingContext context)
19 | : base(info, context) {
20 | }
21 | }
22 |
23 | ///
24 | /// Simple class using Monitor.Enter() and Monitor.Exit()
25 | /// and just like ReaderWriterLockSlim it prevents recursive locks. It doesn't support
26 | /// multiple readers. A reader lock is the same as a writer lock.
27 | ///
28 | class Lock {
29 | readonly object lockObj;
30 | int recurseCount;
31 |
32 | ///
33 | /// Creates a new instance of this class
34 | ///
35 | ///
36 | public static Lock Create() => new Lock();
37 |
38 | ///
39 | /// Constructor
40 | ///
41 | Lock() {
42 | lockObj = new object();
43 | recurseCount = 0;
44 | }
45 |
46 | ///
47 | /// Enter read mode
48 | ///
49 | public void EnterReadLock() {
50 | Monitor.Enter(lockObj);
51 | if (recurseCount != 0) {
52 | Monitor.Exit(lockObj);
53 | throw new LockException("Recursive locks aren't supported");
54 | }
55 | recurseCount++;
56 | }
57 |
58 | ///
59 | /// Exit read mode
60 | ///
61 | public void ExitReadLock() {
62 | if (recurseCount <= 0)
63 | throw new LockException("Too many exit lock method calls");
64 | recurseCount--;
65 | Monitor.Exit(lockObj);
66 | }
67 |
68 | ///
69 | /// Enter write mode
70 | ///
71 | public void EnterWriteLock() {
72 | Monitor.Enter(lockObj);
73 | if (recurseCount != 0) {
74 | Monitor.Exit(lockObj);
75 | throw new LockException("Recursive locks aren't supported");
76 | }
77 | recurseCount--;
78 | }
79 |
80 | ///
81 | /// Exit write mode
82 | ///
83 | public void ExitWriteLock() {
84 | if (recurseCount >= 0)
85 | throw new LockException("Too many exit lock method calls");
86 | recurseCount++;
87 | Monitor.Exit(lockObj);
88 | }
89 | }
90 | #endif
91 | }
92 |
--------------------------------------------------------------------------------
/src/Utils/ArrayEmpty.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | // System namespace so it can easily be replaced with Array.Empty later
4 | namespace System {
5 | static class Array2 {
6 | public static T[] Empty() => EmptyClass.Empty;
7 |
8 | static class EmptyClass {
9 | public static readonly T[] Empty = new T[0];
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Utils/CollectionDebugView.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Diagnostics;
6 | using dnlib.DotNet;
7 | using dnlib.DotNet.Emit;
8 |
9 | namespace dnlib.Utils {
10 | class CollectionDebugView {
11 | readonly ICollection list;
12 | public CollectionDebugView(ICollection list) => this.list = list ?? throw new ArgumentNullException(nameof(list));
13 |
14 | [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
15 | public TValue[] Items {
16 | get {
17 | var array = new TValue[list.Count];
18 | list.CopyTo(array, 0);
19 | return array;
20 | }
21 | }
22 | }
23 |
24 | class CollectionDebugView : CollectionDebugView {
25 | public CollectionDebugView(ICollection list) : base(list) { }
26 | }
27 |
28 | sealed class LocalList_CollectionDebugView : CollectionDebugView {
29 | public LocalList_CollectionDebugView(LocalList list) : base(list) { }
30 | }
31 |
32 | sealed class ParameterList_CollectionDebugView : CollectionDebugView {
33 | public ParameterList_CollectionDebugView(ParameterList list) : base(list) { }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Utils/ILazyList.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System.Collections.Generic;
4 |
5 | namespace dnlib.Utils {
6 | ///
7 | /// Interface to access a lazily initialized list
8 | ///
9 | /// Type to store in list
10 | interface ILazyList : IList {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/W32Resources/ResourceData.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | using System;
4 | using dnlib.IO;
5 |
6 | namespace dnlib.W32Resources {
7 | ///
8 | /// A resource blob
9 | ///
10 | public sealed class ResourceData : ResourceDirectoryEntry {
11 | readonly DataReaderFactory dataReaderFactory;
12 | readonly uint resourceStartOffset;
13 | readonly uint resourceLength;
14 |
15 | uint codePage;
16 | uint reserved;
17 |
18 | ///
19 | /// Gets the data reader
20 | ///
21 | ///
22 | public DataReader CreateReader() => dataReaderFactory.CreateReader(resourceStartOffset, resourceLength);
23 |
24 | ///
25 | /// Gets/sets the code page
26 | ///
27 | public uint CodePage {
28 | get => codePage;
29 | set => codePage = value;
30 | }
31 |
32 | ///
33 | /// Gets/sets the reserved field
34 | ///
35 | public uint Reserved {
36 | get => reserved;
37 | set => reserved = value;
38 | }
39 |
40 | ///
41 | /// Constructor
42 | ///
43 | /// Name
44 | public ResourceData(ResourceName name)
45 | : this(name, ByteArrayDataReaderFactory.Create(Array2.Empty(), filename: null), 0, 0) {
46 | }
47 |
48 | ///
49 | /// Constructor
50 | ///
51 | /// Data reader factory
52 | /// Offset of resource data
53 | /// Length of resource data
54 | /// Name
55 | public ResourceData(ResourceName name, DataReaderFactory dataReaderFactory, uint offset, uint length)
56 | : this(name, dataReaderFactory, offset, length, 0, 0) {
57 | }
58 |
59 | ///
60 | /// Constructor
61 | ///
62 | /// Data reader factory
63 | /// Offset of resource data
64 | /// Length of resource data
65 | /// Name
66 | /// Code page
67 | /// Reserved value
68 | public ResourceData(ResourceName name, DataReaderFactory dataReaderFactory, uint offset, uint length, uint codePage, uint reserved)
69 | : base(name) {
70 | this.dataReaderFactory = dataReaderFactory ?? throw new ArgumentNullException(nameof(dataReaderFactory));
71 | resourceStartOffset = offset;
72 | resourceLength = length;
73 | this.codePage = codePage;
74 | this.reserved = reserved;
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/W32Resources/ResourceDirectoryEntry.cs:
--------------------------------------------------------------------------------
1 | // dnlib: See LICENSE.txt for more info
2 |
3 | namespace dnlib.W32Resources {
4 | ///
5 | /// Base class of and
6 | ///
7 | public abstract class ResourceDirectoryEntry {
8 | ResourceName name;
9 |
10 | ///
11 | /// Gets/sets the name
12 | ///
13 | public ResourceName Name {
14 | get => name;
15 | set => name = value;
16 | }
17 |
18 | ///
19 | /// Constructor
20 | ///
21 | /// Name
22 | protected ResourceDirectoryEntry(ResourceName name) => this.name = name;
23 |
24 | ///
25 | public override string ToString() => name.ToString();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------