├── .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 | --------------------------------------------------------------------------------