diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000..63fd71df8
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,112 @@
+root = true
+
+[*]
+charset = utf-8
+#end_of_line =
+indent_size = 4
+indent_style = tab
+tab_width = 4
+
+[*.json]
+
+[app.config]
+
+[*.yml]
+indent_size = 2
+indent_style = space
+
+[*.{proj,csproj,vbproj,props,targets,resx,vsixmanifest}]
+indent_size = 2
+indent_style = space
+
+[app.manifest]
+indent_size = 2
+indent_style = space
+
+[*.xml]
+
+[*.xaml]
+indent_style = space
+
+[*.{cs,vb}]
+insert_final_newline = true
+
+dotnet_separate_import_directive_groups = false
+dotnet_sort_system_directives_first = true
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_predefined_type_for_locals_parameters_members = true:none
+dotnet_style_predefined_type_for_member_access = true:none
+dotnet_style_prefer_auto_properties = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = false:suggestion
+dotnet_style_qualification_for_event = false:suggestion
+dotnet_style_qualification_for_field = false:suggestion
+dotnet_style_qualification_for_method = false:suggestion
+dotnet_style_qualification_for_property = false:suggestion
+dotnet_style_require_accessibility_modifiers = never:info
+
+[*.cs]
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents = true
+csharp_indent_case_contents_when_block = false
+csharp_indent_labels = flush_left
+csharp_indent_switch_labels = false
+csharp_new_line_before_catch = true
+csharp_new_line_before_else = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_open_brace = none
+csharp_new_line_between_query_expression_clauses = true
+csharp_prefer_braces = false
+csharp_prefer_simple_default_expression = true:suggestion
+#csharp_preferred_modifier_order =
+csharp_preserve_single_line_blocks = true
+csharp_preserve_single_line_statements = true
+csharp_space_after_cast = false
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_after_comma = true
+csharp_space_after_dot = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_around_declaration_statements = false
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_before_comma = false
+csharp_space_before_dot = false
+csharp_space_before_open_square_brackets = false
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_declaration_name_and_open_parenthesis = false
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_parentheses =
+csharp_space_between_square_brackets = false
+csharp_style_conditional_delegate_call = true:suggestion
+csharp_style_deconstructed_variable_declaration = false:none
+csharp_style_expression_bodied_accessors = true:suggestion
+csharp_style_expression_bodied_constructors = true:suggestion
+csharp_style_expression_bodied_indexers = true:suggestion
+csharp_style_expression_bodied_methods = true:suggestion
+csharp_style_expression_bodied_operators = true:suggestion
+csharp_style_expression_bodied_properties = true:suggestion
+csharp_style_inlined_variable_declaration = true:suggestion
+csharp_style_pattern_local_over_anonymous_function = true:suggestion
+csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_throw_expression = true:suggestion
+csharp_style_var_elsewhere = true:suggestion
+csharp_style_var_for_built_in_types = false:none
+csharp_style_var_when_type_is_apparent = true:suggestion
+
+[*.vb]
+#visual_basic_preferred_modifier_order =
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 000000000..1071e16bc
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,78 @@
+name: GitHub CI
+on:
+ push:
+ paths:
+ - '.github/workflows/**'
+ - 'Examples/**'
+ - 'src/**'
+ - '!**/*.md'
+ branches:
+ - master
+ pull_request:
+ paths:
+ - 'Examples/**'
+ - 'src/**'
+ - '!**/*.md'
+ branches:
+ - master
+ release:
+ types: released
+
+env:
+ CI_REQ_DOTNET_SDK_VER: 6.0.100
+
+jobs:
+ build-windows:
+ name: Build (Windows)
+ runs-on: windows-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: ${{env.CI_REQ_DOTNET_SDK_VER}}
+
+ - name: Build
+ shell: pwsh
+ run: |
+ $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
+ $env:PATH = $msbuildPath + ';' + $env:PATH
+ .\build.ps1
+
+ - name: upload-artifact doesn't support wildcards
+ if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')
+ shell: pwsh
+ run: |
+ New-Item -ItemType Directory nuget_files > $null
+ Copy-Item src\bin\Release\*.*nupkg nuget_files
+
+ - uses: actions/upload-artifact@v4
+ if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')
+ with:
+ name: nupkg
+ path: nuget_files
+ if-no-files-found: error
+
+ - name: Upload to nuget.org if it's a new release
+ if: startsWith(github.ref, 'refs/tags/')
+ shell: pwsh
+ run: |
+ Invoke-WebRequest -Uri https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -UseBasicParsing -OutFile nuget.exe
+ 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 }
+
+ # Make sure it builds on Linux too
+ build-ubuntu:
+ name: Build (Ubuntu)
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: ${{env.CI_REQ_DOTNET_SDK_VER}}
+
+ - name: Build
+ shell: pwsh
+ run: ./build.ps1
diff --git a/.gitignore b/.gitignore
index 85f65d4d2..f6adf54ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,4 @@
-*~
-*/obj/
-*.csproj.user
-*.sdf
-*.opensdf
-*.suo
-/Debug/
-/Release/
-/Examples/bin/
-*.tmp_proj
+.vs/
+.vscode/
+bin/
+obj/
diff --git a/Examples/Example1.cs b/Examples/Example1.cs
index c866bec13..e2b5dd3e5 100644
--- a/Examples/Example1.cs
+++ b/Examples/Example1.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using dnlib.DotNet;
namespace dnlib.Examples {
@@ -8,17 +8,17 @@ namespace dnlib.Examples {
public class Example1 {
public static void Run() {
// Load mscorlib.dll
- string filename = typeof(void).Module.FullyQualifiedName;
- ModuleDefMD mod = ModuleDefMD.Load(filename);
+ var filename = typeof(void).Module.FullyQualifiedName;
+ var mod = ModuleDefMD.Load(filename);
int totalNumTypes = 0;
// mod.Types only returns non-nested types.
// mod.GetTypes() returns all types, including nested types.
- foreach (TypeDef type in mod.GetTypes()) {
+ foreach (var type in mod.GetTypes()) {
totalNumTypes++;
Console.WriteLine();
Console.WriteLine("Type: {0}", type.FullName);
- if (type.BaseType != null)
+ if (type.BaseType is not null)
Console.WriteLine(" Base type: {0}", type.BaseType.FullName);
Console.WriteLine(" Methods: {0}", type.Methods.Count);
@@ -29,7 +29,7 @@ public static void Run() {
if (type.Interfaces.Count > 0) {
Console.WriteLine(" Interfaces:");
- foreach (InterfaceImpl iface in type.Interfaces)
+ foreach (var iface in type.Interfaces)
Console.WriteLine(" {0}", iface.Interface.FullName);
}
}
diff --git a/Examples/Example2.cs b/Examples/Example2.cs
index 476cde7df..97926d504 100644
--- a/Examples/Example2.cs
+++ b/Examples/Example2.cs
@@ -1,4 +1,4 @@
-using dnlib.DotNet;
+using dnlib.DotNet;
using dnlib.DotNet.Emit;
namespace dnlib.Examples {
@@ -7,10 +7,10 @@ public class Example2 {
// and then save the assembly to disk.
public static void Run() {
// Open the current module
- ModuleDefMD mod = ModuleDefMD.Load(typeof(Example2).Module);
+ var mod = ModuleDefMD.Load(typeof(Example2).Module);
// Create a new public class that derives from System.Object
- TypeDef type1 = new TypeDefUser("My.Namespace", "MyType",
+ var type1 = new TypeDefUser("My.Namespace", "MyType",
mod.CorLibTypes.Object.TypeDefOrRef);
type1.Attributes = TypeAttributes.Public | TypeAttributes.AutoLayout |
TypeAttributes.Class | TypeAttributes.AnsiClass;
@@ -19,7 +19,7 @@ public static void Run() {
mod.Types.Add(type1);
// Create a public static System.Int32 field called MyField
- FieldDef field1 = new FieldDefUser("MyField",
+ var field1 = new FieldDefUser("MyField",
new FieldSig(mod.CorLibTypes.Int32),
FieldAttributes.Public | FieldAttributes.Static);
// Add it to the type we created earlier
@@ -27,22 +27,22 @@ public static void Run() {
// Add a static method that adds both inputs and the static field
// and returns the result
- MethodImplAttributes methImplFlags = MethodImplAttributes.IL | MethodImplAttributes.Managed;
- MethodAttributes methFlags = MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot;
- MethodDef meth1 = new MethodDefUser("MyMethod",
+ var methImplFlags = MethodImplAttributes.IL | MethodImplAttributes.Managed;
+ var methFlags = MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot;
+ var meth1 = new MethodDefUser("MyMethod",
MethodSig.CreateStatic(mod.CorLibTypes.Int32, mod.CorLibTypes.Int32, mod.CorLibTypes.Int32),
methImplFlags, methFlags);
type1.Methods.Add(meth1);
// Create the CIL method body
- CilBody body = new CilBody();
+ var body = new CilBody();
meth1.Body = body;
// Name the 1st and 2nd args a and b, respectively
meth1.ParamDefs.Add(new ParamDefUser("a", 1));
meth1.ParamDefs.Add(new ParamDefUser("b", 2));
// Create a local. We don't really need it but let's add one anyway
- Local local1 = new Local(mod.CorLibTypes.Int32);
+ var local1 = new Local(mod.CorLibTypes.Int32);
body.Variables.Add(local1);
// Add the instructions, and use the useless local
diff --git a/Examples/Example3.cs b/Examples/Example3.cs
index 62688233c..30e919d74 100644
--- a/Examples/Example3.cs
+++ b/Examples/Example3.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Text;
using dnlib.DotNet;
using dnlib.DotNet.Emit;
@@ -23,12 +23,12 @@ public class Example3 {
public static void Run() {
// Create a new module. The string passed in is the name of the module,
// not the file name.
- ModuleDef mod = new ModuleDefUser("MyModule.exe");
+ var mod = new ModuleDefUser("MyModule.exe");
// It's a console application
mod.Kind = ModuleKind.Console;
// Add the module to an assembly
- AssemblyDef asm = new AssemblyDefUser("MyAssembly", new Version(1, 2, 3, 4), null, null);
+ var asm = new AssemblyDefUser("MyAssembly", new Version(1, 2, 3, 4), null, null);
asm.Modules.Add(mod);
// Add a .NET resource
@@ -37,14 +37,14 @@ public static void Run() {
ManifestResourceAttributes.Private));
// Add the startup type. It derives from System.Object.
- TypeDef startUpType = new TypeDefUser("My.Namespace", "Startup", mod.CorLibTypes.Object.TypeDefOrRef);
+ var startUpType = new TypeDefUser("My.Namespace", "Startup", mod.CorLibTypes.Object.TypeDefOrRef);
startUpType.Attributes = TypeAttributes.NotPublic | TypeAttributes.AutoLayout |
TypeAttributes.Class | TypeAttributes.AnsiClass;
// Add the type to the module
mod.Types.Add(startUpType);
// Create the entry point method
- MethodDef entryPoint = new MethodDefUser("Main",
+ var entryPoint = new MethodDefUser("Main",
MethodSig.CreateStatic(mod.CorLibTypes.Int32, new SZArraySig(mod.CorLibTypes.String)));
entryPoint.Attributes = MethodAttributes.Private | MethodAttributes.Static |
MethodAttributes.HideBySig | MethodAttributes.ReuseSlot;
@@ -57,14 +57,14 @@ public static void Run() {
mod.EntryPoint = entryPoint;
// Create a TypeRef to System.Console
- TypeRef consoleRef = new TypeRefUser(mod, "System", "Console", mod.CorLibTypes.AssemblyRef);
+ var consoleRef = new TypeRefUser(mod, "System", "Console", mod.CorLibTypes.AssemblyRef);
// Create a method ref to 'System.Void System.Console::WriteLine(System.String)'
- MemberRef consoleWrite1 = new MemberRefUser(mod, "WriteLine",
+ var consoleWrite1 = new MemberRefUser(mod, "WriteLine",
MethodSig.CreateStatic(mod.CorLibTypes.Void, mod.CorLibTypes.String),
consoleRef);
// Add a CIL method body to the entry point method
- CilBody epBody = new CilBody();
+ var epBody = new CilBody();
entryPoint.Body = epBody;
epBody.Instructions.Add(OpCodes.Ldstr.ToInstruction("Hello World!"));
epBody.Instructions.Add(OpCodes.Call.ToInstruction(consoleWrite1));
diff --git a/Examples/Example4.cs b/Examples/Example4.cs
index 04f6de693..a2dd34005 100644
--- a/Examples/Example4.cs
+++ b/Examples/Example4.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using dnlib.DotNet;
using dnlib.DotNet.Emit;
diff --git a/Examples/Example5.cs b/Examples/Example5.cs
index edb26243f..8116fe53f 100644
--- a/Examples/Example5.cs
+++ b/Examples/Example5.cs
@@ -1,8 +1,6 @@
-using System;
+using System;
using System.IO;
using dnlib.DotNet;
-using dnlib.PE;
-using dnlib.IO;
namespace dnlib.Examples {
///
@@ -16,7 +14,7 @@ public static void Run() {
var mod = ModuleDefMD.Load(typeof(int).Module);
// Get PE image interface
- var peImage = mod.MetaData.PEImage;
+ var peImage = mod.Metadata.PEImage;
// Print some info
Console.WriteLine("Machine: {0}", peImage.ImageNTHeaders.FileHeader.Machine);
@@ -26,13 +24,13 @@ public static void Run() {
for (int i = 0; i < peImage.ImageSectionHeaders.Count; i++) {
var section = peImage.ImageSectionHeaders[i];
- // Create a stream for the whole section
- var stream = peImage.CreateStream(section.VirtualAddress, section.SizeOfRawData);
+ // Create a reader for the whole section
+ var reader = peImage.CreateReader(section.VirtualAddress, section.SizeOfRawData);
// Write the data to disk
var fileName = string.Format(sectionFileName, i);
Console.WriteLine("Dumping section {0} to file {1}", section.DisplayName, fileName);
- File.WriteAllBytes(fileName, stream.ReadAllBytes());
+ File.WriteAllBytes(fileName, reader.ToArray());
}
}
}
diff --git a/Examples/Example6.cs b/Examples/Example6.cs
index 00b196a0b..d92add484 100644
--- a/Examples/Example6.cs
+++ b/Examples/Example6.cs
@@ -1,5 +1,4 @@
-using System;
-using System.IO;
+using System;
using dnlib.DotNet;
using dnlib.DotNet.MD;
using dnlib.DotNet.Writer;
@@ -8,15 +7,13 @@
namespace dnlib.Examples {
///
- /// This example shows how to create a module writer listener that gets notified of various
+ /// This example shows how to add a module writer listener that gets notified of various
/// events. This listener just adds a new PE section to the image and prints the new RIDs.
/// It also shows how to add some dummy .NET heaps, and simple obfuscation that will break
/// most libraries that open .NET assemblies.
///
- public class Example6 : IModuleWriterListener {
- public static void Run() {
- new Example6().DoIt();
- }
+ public class Example6 {
+ public static void Run() => new Example6().DoIt();
void DoIt() {
string destFileName = @"c:\output.dll";
@@ -28,7 +25,7 @@ void DoIt() {
var opts = new ModuleWriterOptions(mod);
// Add a listener that gets notified during the writing process
- opts.Listener = this;
+ opts.WriterEvent += OnWriterEvent;
// This is normally 16 but setting it to a value less than 14 will fool some
// apps into thinking that there's no .NET metadata available
@@ -36,15 +33,18 @@ void DoIt() {
// Add extra data. This will break most libraries that open .NET assemblies.
// Any value can be written here.
- opts.MetaDataOptions.TablesHeapOptions.ExtraData = 0x12345678;
+ opts.MetadataOptions.TablesHeapOptions.ExtraData = 0x12345678;
// Add a few dummy heaps
- opts.MetaDataOptions.OtherHeaps.Add(new MyHeap("#US "));
- opts.MetaDataOptions.OtherHeaps.Add(new MyHeap("#Strings "));
- opts.MetaDataOptions.OtherHeaps.Add(new MyHeap("#Strimgs"));
- opts.MetaDataOptions.OtherHeaps.Add(new MyHeap("#GU1D"));
- opts.MetaDataOptions.OtherHeapsEnd.Add(new MyHeap("#US "));
- opts.MetaDataOptions.OtherHeapsEnd.Add(new MyHeap("#Strings "));
+ opts.MetadataOptions.CustomHeaps.Add(new MyHeap("#US "));
+ opts.MetadataOptions.CustomHeaps.Add(new MyHeap("#Strings "));
+ opts.MetadataOptions.CustomHeaps.Add(new MyHeap("#Strimgs"));
+ opts.MetadataOptions.CustomHeaps.Add(new MyHeap("#GU1D"));
+ opts.MetadataOptions.CustomHeaps.Add(new MyHeap("#US "));
+ opts.MetadataOptions.CustomHeaps.Add(new MyHeap("#Strings "));
+ opts.MetadataOptions.MetadataHeapsAdded += (s, e) => {
+ // You could sort the heaps here
+ };
// Write the module. The listener will get notified, see OnWriterEvent() below
mod.Write(destFileName, opts);
@@ -59,56 +59,37 @@ class MyHeap : IHeap {
// This is the data. I chose 10 bytes, but any non-zero value can be used
byte[] heapData = new byte[10];
- public MyHeap(string name) {
- this.name = name;
- }
+ public MyHeap(string name) => this.name = name;
// The rest of the code is just for implementing the required interface
- public string Name {
- get { return name; }
- }
-
- public bool IsEmpty {
- get { return false; }
- }
+ public string Name => name;
+ public bool IsEmpty => false;
public void SetReadOnly() {
}
- public FileOffset FileOffset {
- get { return offset; }
- }
-
- public RVA RVA {
- get { return rva; }
- }
+ public FileOffset FileOffset => offset;
+ public RVA RVA => rva;
public void SetOffset(FileOffset offset, RVA rva) {
this.offset = offset;
this.rva = rva;
}
- public uint GetFileLength() {
- return (uint)heapData.Length;
- }
-
- public uint GetVirtualSize() {
- return GetFileLength();
- }
-
- public void WriteTo(BinaryWriter writer) {
- writer.Write(heapData);
- }
+ public uint GetFileLength() => (uint)heapData.Length;
+ public uint GetVirtualSize() => GetFileLength();
+ public uint CalculateAlignment() => 0;
+ public void WriteTo(DataWriter writer) => writer.WriteBytes(heapData);
}
// Gets notified during module writing
- public void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) {
- switch (evt) {
+ void OnWriterEvent(object sender, ModuleWriterEventArgs e) {
+ switch (e.Event) {
case ModuleWriterEvent.PESectionsCreated:
// Add a PE section
var sect1 = new PESection(".dummy", 0x40000040);
- writer.Sections.Add(sect1);
+ e.Writer.AddSection(sect1);
// Let's add data
sect1.Add(new ByteArrayChunk(new byte[123]), 4);
sect1.Add(new ByteArrayChunk(new byte[10]), 4);
@@ -117,15 +98,15 @@ public void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) {
case ModuleWriterEvent.MDEndCreateTables:
// All types, methods etc have gotten their new RIDs. Let's print the new values
Console.WriteLine("Old -> new type and method tokens");
- foreach (var type in writer.Module.GetTypes()) {
+ foreach (var type in e.Writer.Module.GetTypes()) {
Console.WriteLine("TYPE: {0:X8} -> {1:X8} {2}",
type.MDToken.Raw,
- new MDToken(Table.TypeDef, writer.MetaData.GetRid(type)).Raw,
+ new MDToken(Table.TypeDef, e.Writer.Metadata.GetRid(type)).Raw,
type.FullName);
foreach (var method in type.Methods)
Console.WriteLine(" METH: {0:X8} -> {1:X8} {2}",
method.MDToken.Raw,
- new MDToken(Table.Method, writer.MetaData.GetRid(method)).Raw,
+ new MDToken(Table.Method, e.Writer.Metadata.GetRid(method)).Raw,
method.FullName);
}
break;
diff --git a/Examples/Example7.cs b/Examples/Example7.cs
new file mode 100644
index 000000000..32c699885
--- /dev/null
+++ b/Examples/Example7.cs
@@ -0,0 +1,69 @@
+using System;
+using System.IO;
+using System.Linq;
+using dnlib.DotNet;
+using dnlib.DotNet.Emit;
+
+namespace dnlib.Examples {
+ public class Example7 {
+ public static void Run() => new Example7().DoIt();
+
+ void DoIt() {
+ var test1 = new OpCode(
+ "test1", 0xf0, 0x00, OperandType.InlineNone, FlowControl.Next, StackBehaviour.Push0, StackBehaviour.Pop0);
+ var test2 = new OpCode(
+ "test2", 0xf0, 0x01, OperandType.InlineBrTarget, FlowControl.Branch, StackBehaviour.Push0, StackBehaviour.Pop0);
+ var test3 = new OpCode(
+ "test3", 0xf0, 0x02, OperandType.InlineString, FlowControl.Next, StackBehaviour.Push1, StackBehaviour.Pop0);
+
+ var ctx = new ModuleContext();
+
+ ctx.RegisterExperimentalOpCode(test1);
+ ctx.RegisterExperimentalOpCode(test2);
+ ctx.RegisterExperimentalOpCode(test3);
+
+ var mod = ModuleDefMD.Load(typeof(Example7).Module, ctx);
+ var body = mod.Types.Single(x => x.Name == nameof(Example7)).Methods.Single(x => x.Name == nameof(CustomCil)).Body;
+
+ Console.WriteLine("Original:");
+ foreach (var insn in body.Instructions)
+ Console.WriteLine("{0} (0x{1:X4})", insn, insn.OpCode.Value);
+ Console.WriteLine();
+
+ var code = body.Instructions;
+
+ code.Clear();
+
+ var label = OpCodes.Nop.ToInstruction();
+
+ code.Add(test1.ToInstruction());
+ code.Add(OpCodes.Nop.ToInstruction());
+ code.Add(label);
+ code.Add(OpCodes.Ret.ToInstruction());
+ code.Add(test2.ToInstruction(label));
+ code.Add(test3.ToInstruction("foo"));
+
+ Console.WriteLine("Modified:");
+ foreach (var insn in body.Instructions)
+ Console.WriteLine("{0} (0x{1:X4})", insn, insn.OpCode.Value);
+ Console.WriteLine();
+
+ using (var stream = new MemoryStream()) {
+ mod.Write(stream);
+
+ stream.Position = 0;
+
+ mod = ModuleDefMD.Load(stream, ctx);
+ body = mod.Types.Single(x => x.Name == nameof(Example7)).Methods.Single(x => x.Name == nameof(CustomCil)).Body;
+
+ Console.WriteLine("Roundtripped:");
+ foreach (var insn in body.Instructions)
+ Console.WriteLine("{0} (0x{1:X4})", insn, insn.OpCode.Value);
+ Console.WriteLine();
+ }
+ }
+
+ void CustomCil() {
+ }
+ }
+}
diff --git a/Examples/Examples.csproj b/Examples/Examples.csproj
index 1773222b6..3bd7f6613 100644
--- a/Examples/Examples.csproj
+++ b/Examples/Examples.csproj
@@ -1,59 +1,18 @@
-
-
+
+
- Debug
- x86
- 8.0.30703
- 2.0
- {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}
+ net6.0;net45Exe
- Properties
- dnlib.Examples
- dnlib.Examples
- v2.0
- 512
-
-
- x86
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- x86
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
+ false
+ latest
+
-
-
-
-
-
-
-
-
+
+
-
- {FDFC1237-143F-4919-8318-4926901F4639}
- dnlib
-
+
-
-
-
\ No newline at end of file
+
+
diff --git a/Examples/Program.cs b/Examples/Program.cs
index 434e24627..e22415ad6 100644
--- a/Examples/Program.cs
+++ b/Examples/Program.cs
@@ -1,4 +1,4 @@
-namespace dnlib.Examples {
+namespace dnlib.Examples {
class Program {
static void Main(string[] args) {
// Just uncomment whatever you want to debug
@@ -7,7 +7,8 @@ static void Main(string[] args) {
// Example3.Run();
// Example4.Run();
// Example5.Run();
- Example6.Run();
+// Example6.Run();
+ Example7.Run();
}
}
}
diff --git a/Examples/Properties/AssemblyInfo.cs b/Examples/Properties/AssemblyInfo.cs
deleted file mode 100644
index 556b997b6..000000000
--- a/Examples/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle("dnlib.Examples")]
-[assembly: AssemblyDescription("dnlib examples")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("dnlib.Examples")]
-[assembly: AssemblyCopyright("Copyright (C) 2012-2014 de4dot@gmail.com")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-[assembly: ComVisible(false)]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/LICENSE.txt b/LICENSE.txt
index 1d6e3873d..74858b859 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,16 +1,4 @@
-dnlib: .NET assembly library
-https://github.com/0xd4d/dnlib
-
-Copyright (C) 2012-2015 de4dot@gmail.com
-
-Contributors
-------------
-
-Ki, "yck1509 ", https://github.com/yck1509
-kiootic, "kiootic ", https://github.com/kiootic
-
-MIT LICENSE
------------
+Copyright (C) 2012-2019 de4dot@gmail.com
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/README.md b/README.md
index 8f517429f..0cee42416 100644
--- a/README.md
+++ b/README.md
@@ -1,96 +1,74 @@
-.NET module/assembly reader/writer library written for [de4dot](https://github.com/0xd4d/de4dot/).
+# dnlib [](https://www.nuget.org/packages/dnlib/) [](https://github.com/0xd4d/dnlib/actions)
-
-dnlib was created because de4dot needed a robust .NET assembly library that
-could handle all types of obfuscated assemblies. de4dot used to use Mono.Cecil
-but since Mono.Cecil can't handle obfuscated assemblies, doesn't fully support
-mixed mode assemblies, doesn't read .NET assemblies the same way the [CLR](http://en.wikipedia.org/wiki/Common_Language_Runtime) does
-and many other missing features de4dot needed, dnlib was a necessity. The API
-is similar because it made porting de4dot to dnlib a lot easier.
-
-For another application using dnlib, see [ConfuserEx](https://github.com/yck1509/ConfuserEx/)
-(a .NET obfuscator). It uses many of the more advanced features of dnlib. Have
-a look at its writer code which gets executed during the assembly writing
-process.
-
-Compiling
----------
-
-You must have Visual Studio 2008 or later. The solution file was created by
-Visual Studio 2010, so if you use VS2008, open the solution file and change the
-version number so VS2008 can read it.
-
-Examples
---------
-
-All examples use C#, but since it's a .NET library, you can use any .NET
-language (eg. VB.NET).
-
-See the Examples project for several examples.
+.NET module/assembly reader/writer library
Opening a .NET assembly/module
------------------------------
-First of all, the important namespaces are `dnlib.DotNet` and
-`dnlib.DotNet.Emit`. `dnlib.DotNet.Emit` is only needed if you intend to
-read/write method bodies. All the examples below assume you have the
-appropriate using statements at the top of each source file:
+First of all, the important namespaces are `dnlib.DotNet` and `dnlib.DotNet.Emit`. `dnlib.DotNet.Emit` is only needed if you intend to read/write method bodies. All the examples below assume you have the appropriate using statements at the top of each source file:
-```csharp
+```C#
using dnlib.DotNet;
using dnlib.DotNet.Emit;
```
-ModuleDefMD is the class that is created when you open a .NET module. It has
-several `Load()` methods that will create a ModuleDefMD instance. If it's not a
-.NET module/assembly, a `BadImageFormatException` will be thrown.
+ModuleDefMD is the class that is created when you open a .NET module. It has several `Load()` methods that will create a ModuleDefMD instance. If it's not a .NET module/assembly, a `BadImageFormatException` will be thrown.
Read a .NET module from a file:
-```csharp
- ModuleDefMD module = ModuleDefMD.Load(@"C:\path\to\file.exe");
+```C#
+ // Create a default assembly resolver and type resolver and pass it to Load().
+ // If it's a .NET Core assembly, you'll need to disable GAC loading and add
+ // .NET Core reference assembly search paths.
+ ModuleContext modCtx = ModuleDef.CreateModuleContext();
+ ModuleDefMD module = ModuleDefMD.Load(@"C:\path\to\file.exe", modCtx);
```
Read a .NET module from a byte array:
-```csharp
+```C#
byte[] data = System.IO.File.ReadAllBytes(@"C:\path\of\file.dll");
- ModuleDefMD module = ModuleDefMD.Load(data);
+ // See comment above about the assembly resolver
+ ModuleContext modCtx = ModuleDef.CreateModuleContext();
+ ModuleDefMD module = ModuleDefMD.Load(data, modCtx);
```
-You can also pass in a Stream instance, an address in memory (HINSTANCE) or
-even a System.Reflection.Module instance:
+You can also pass in a Stream instance, an address in memory (HINSTANCE) or even a System.Reflection.Module instance:
-```csharp
+```C#
System.Reflection.Module reflectionModule = typeof(void).Module; // Get mscorlib.dll's module
- ModuleDefMD module = ModuleDefMD.Load(reflectionModule);
+ // See comment above about the assembly resolver
+ ModuleContext modCtx = ModuleDef.CreateModuleContext();
+ ModuleDefMD module = ModuleDefMD.Load(reflectionModule, modCtx);
```
To get the assembly, use its Assembly property:
-```csharp
+```C#
AssemblyDef asm = module.Assembly;
Console.WriteLine("Assembly: {0}", asm);
```
+If it's an obfuscated Unity/Mono assembly, you need to create a `ModuleCreationOptions` instance and write `CLRRuntimeReaderKind.Mono` to `ModuleCreationOptions.Runtime` and pass in this `ModuleCreationOptions` instance to one of the `ModuleDefMD.Load(...)` methods.
+
Saving a .NET assembly/module
-----------------------------
Use `module.Write()`. It can save the assembly to a file or a Stream.
-```csharp
+```C#
module.Write(@"C:\saved-assembly.dll");
```
If it's a C++/CLI assembly, you should use `NativeWrite()`
-```csharp
+```C#
module.NativeWrite(@"C:\saved-assembly.dll");
```
To detect it at runtime, use this code:
-```csharp
+```C#
if (module.IsILOnly) {
// This assembly has only IL code, and no native code (eg. it's a C# or VB assembly)
module.Write(@"C:\saved-assembly.dll");
@@ -104,28 +82,14 @@ To detect it at runtime, use this code:
PDB files
---------
-Right after opening the module, call one of its `LoadPdb()` methods. You can
-also pass in a `ModuleCreationOptions` to `ModuleDefMD.Load()` and if one of
-the PDB options is enabled, the PDB file will be opened before `Load()`
-returns.
+PDB files are read from disk by default. You can change this behaviour by creating a `ModuleCreationOptions` and passing it in to the code that creates a module.
-```csharp
- var mod = ModuleDefMD.Load(@"C:\myfile.dll");
- mod.LoadPdb(); // Will load C:\myfile.pdb if it exists
-```
+To save a PDB file, create a `ModuleWriterOptions` / `NativeModuleWriterOptions` and set its `WritePdb` property to `true`. By default, it will create a PDB file with the same name as the output assembly but with a `.pdb` extension. You can override this by writing the PDB file name to `PdbFileName` or writing your own stream to `PdbStream`. If `PdbStream` is initialized, `PdbFileName` should also be initialized because the name of the PDB file will be written to the PE file.
-To save a PDB file, create a `ModuleWriterOptions` /
-`NativeModuleWriterOptions` and set its `WritePdb` property to `true`. By
-default, it will create a PDB file with the same name as the output assembly
-but with a `.pdb` extension. You can override this by writing the PDB file
-name to `PdbFileName` or writing your own stream to `PdbStream`. If
-`PdbStream` is initialized, `PdbFileName` should also be initialized because
-the name of the PDB file will be written to the PE file. Another more
-advanced property is `CreatePdbSymbolWriter` which returns a `ISymbolWriter2`
-instance that dnlib will use.
-
-```csharp
- var mod = ModuleDefMD.Load(@"C:\myfile.dll");
+```C#
+ // Create a default assembly resolver and type resolver
+ ModuleContext modCtx = ModuleDef.CreateModuleContext();
+ var mod = ModuleDefMD.Load(@"C:\myfile.dll", modCtx);
// ...
var wopts = new dnlib.DotNet.Writer.ModuleWriterOptions(mod);
wopts.WritePdb = true;
@@ -133,17 +97,25 @@ instance that dnlib will use.
mod.Write(@"C:\out.dll", wopts);
```
-There exist two different types of PDB readers, one is using the Microsoft
-COM PDB API available in diasymreader.dll (for Windows only), and the other
-one, which is now the default implementation, is a managed PDB reader. The PDB
-writer currently only uses the COM PDB API so will only work on Windows.
+dnlib supports Windows PDBs, portable PDBs and embedded portable PDBs.
-Strong name sign an assembly
-----------------------------
+Windows PDBs
+------------
+
+It's only possible to write Windows PDBs on Windows (portable PDBs can be written on any OS). dnlib has a managed Windows PDB reader that supports all OSes.
+
+There are two *native* Windows PDB reader and writer implementations, the old `diasymreader.dll` that ships with .NET Framework and `Microsoft.DiaSymReader.Native` which has been updated with more features and bug fixes.
+
+dnlib will use `Microsoft.DiaSymReader.Native` if it exists and fall back to `diasymreader.dll` if needed. `PdbReaderOptions` and `PdbWriterOptions` can be used to disable one of them.
+
+`Microsoft.DiaSymReader.Native` is a NuGet package with 32-bit and 64-bit native DLLs. You have to add a reference to this NuGet package if you want dnlib to use it. dnlib doesn't add a reference to it.
+
+Strong name signing an assembly
+-------------------------------
Use the following code to strong name sign the assembly when saving it:
-```csharp
+```C#
using dnlib.DotNet.Writer;
...
// Open or create an assembly
@@ -165,12 +137,11 @@ Use the following code to strong name sign the assembly when saving it:
Enhanced strong name signing an assembly
----------------------------------------
-See this [MSDN article](http://msdn.microsoft.com/en-us/library/hh415055.aspx)
-for info on enhanced strong naming.
+See this [MSDN article](http://msdn.microsoft.com/en-us/library/hh415055.aspx) for info on enhanced strong naming.
Enhanced strong name signing without key migration:
-```csharp
+```C#
using dnlib.DotNet.Writer;
...
// Open or create an assembly
@@ -192,7 +163,7 @@ Enhanced strong name signing without key migration:
Enhanced strong name signing with key migration:
-```csharp
+```C#
using dnlib.DotNet.Writer;
...
// Open or create an assembly
@@ -215,59 +186,86 @@ Enhanced strong name signing with key migration:
mod.Write(@"C:\out\file.dll", opts);
```
+Exporting managed methods (DllExport)
+-------------------------------------
+
+dnlib supports exporting managed methods so the managed DLL file can be loaded by native code and then executed. .NET Framework supports this feature, but there's no guarantee that other CLRs (eg. .NET Core or Mono/Unity) support this feature.
+In case of .NET Core please be aware that `ijwhost.dll` has to be loaded prior to calling your exported method and that ijwhost currently (as of .NET Core 3.0) does not work if the calling app is self-contained.
+
+The `MethodDef` class has an `ExportInfo` property. If it gets initialized, the method gets exported when saving the module. At most 65536 (2^16) methods can be exported. This is a PE file limitation, not a dnlib limitation.
+
+Exported methods should not be generic.
+
+The method's calling convention should be changed to eg. stdcall, or cdecl, by adding an optional modifier to `MethodDef.MethodSig.RetType`. It must be a `System.Runtime.CompilerServices.CallConvCdecl`, `System.Runtime.CompilerServices.CallConvStdcall`, `System.Runtime.CompilerServices.CallConvThiscall`, or a `System.Runtime.CompilerServices.CallConvFastcall`, eg.:
+
+```C#
+var type = method.MethodSig.RetType;
+type = new CModOptSig(module.CorLibTypes.GetTypeRef("System.Runtime.CompilerServices", "CallConvCdecl"), type);
+method.MethodSig.RetType = type;
+```
+
+Requirements:
+
+- The assembly platform must be x86, x64, IA-64 or ARM (ARM64 isn't supported at the moment). AnyCPU assemblies are not supported. This is as simple as changing (if needed) `ModuleWriterOptions.PEHeadersOptions.Machine` when saving the file. x86 files should set `32-bit required` flag and clear `32-bit preferred` flag in the COR20 header.
+- `ModuleWriterOptions.Cor20HeaderOptions.Flags`: The `IL Only` bit must be cleared.
+- It must be a DLL file (see `ModuleWriterOptions.PEHeadersOptions.Characteristics`). The file will fail to load at runtime if it's an EXE file.
+
+NOTE: VS' debugger crashes if there's a `DebuggableAttribute` attribute and if the first ctor arg is 0x107. The workaround is to clear the `EnableEditAndContinue` bit:
+
+```C#
+var ca = module.Assembly.CustomAttributes.Find("System.Diagnostics.DebuggableAttribute");
+if (ca is not null && ca.ConstructorArguments.Count == 1) {
+ var arg = ca.ConstructorArguments[0];
+ // VS' debugger crashes if value == 0x107, so clear EnC bit
+ if (arg.Type.FullName == "System.Diagnostics.DebuggableAttribute/DebuggingModes" && arg.Value is int value && value == 0x107) {
+ arg.Value = value & ~(int)DebuggableAttribute.DebuggingModes.EnableEditAndContinue;
+ ca.ConstructorArguments[0] = arg;
+ }
+}
+```
+
+See the following issues: [#271](https://github.com/0xd4d/dnlib/issues/271), [#172](https://github.com/0xd4d/dnlib/issues/172)
+
Type classes
------------
-The metadata has three type tables: `TypeRef`, `TypeDef`, and `TypeSpec`. The
-classes dnlib use are called the same. These three classes all implement
-`ITypeDefOrRef`.
+The metadata has three type tables: `TypeRef`, `TypeDef`, and `TypeSpec`. The classes dnlib use are called the same. These three classes all implement `ITypeDefOrRef`.
-There's also type signature classes. The base class is `TypeSig`. You'll find
-`TypeSig`s in method signatures (return type and parameter types) and locals.
-The `TypeSpec` class also has a `TypeSig` property.
+There's also type signature classes. The base class is `TypeSig`. You'll find `TypeSig`s in method signatures (return type and parameter types) and locals. The `TypeSpec` class also has a `TypeSig` property.
All of these types implement `IType`.
`TypeRef` is a reference to a type in (usually) another assembly.
-`TypeDef` is a type definition and it's a type defined in some module. This
-class does *not* derive from `TypeRef`. :)
+`TypeDef` is a type definition and it's a type defined in some module. This class does *not* derive from `TypeRef`. :)
`TypeSpec` can be a generic type, an array type, etc.
-`TypeSig` is the base class of all type signatures (found in method sigs and
-locals). It has a `Next` property that points to the next `TypeSig`. Eg. a
-Byte[] would first contain a `SZArraySig`, and its `Next` property would point
-to Byte signature.
+`TypeSig` is the base class of all type signatures (found in method sigs and locals). It has a `Next` property that points to the next `TypeSig`. Eg. a Byte[] would first contain a `SZArraySig`, and its `Next` property would point to Byte signature.
-`CorLibTypeSig` is a simple corlib type. You don't create these directly. Use
-eg. `module.CorLibTypes.Int32` to get a System.Int32 type signature.
+`CorLibTypeSig` is a simple corlib type. You don't create these directly. Use eg. `module.CorLibTypes.Int32` to get a System.Int32 type signature.
`ValueTypeSig` is used when the next class is a value type.
`ClassSig` is used when the next class is a reference type.
-`GenericInstSig` is a generic instance type. It has a reference to the generic
-type (a `TypeDef` or a `TypeRef`) and the generic arguments.
+`GenericInstSig` is a generic instance type. It has a reference to the generic type (a `TypeDef` or a `TypeRef`) and the generic arguments.
`PtrSig` is a pointer sig.
`ByRefSig` is a by reference type.
-`ArraySig` is a multi-dimensional array type. Most likely when you create an
-array, you should use `SZArraySig`, and *not* `ArraySig`.
+`ArraySig` is a multi-dimensional array type. Most likely when you create an array, you should use `SZArraySig`, and *not* `ArraySig`.
-`SZArraySig` is a single dimension, zero lower bound array. In C#, a `byte[]`
-is a `SZArraySig`, and *not* an `ArraySig`.
+`SZArraySig` is a single dimension, zero lower bound array. In C#, a `byte[]` is a `SZArraySig`, and *not* an `ArraySig`.
`GenericVar` is a generic type variable.
`GenericMVar` is a generic method variable.
-Some examples if you're not used to the way type signatures are represented
-in metadata:
+Some examples if you're not used to the way type signatures are represented in metadata:
-```csharp
+```C#
ModuleDef mod = ....;
// Create a byte[]
@@ -288,10 +286,9 @@ in metadata:
SZArraySig array5 = new SZArraySig(new ClassSig(stream));
```
-Sometimes you must convert an `ITypeDefOrRef` (`TypeRef`, `TypeDef`, or
-`TypeSpec`) to/from a `TypeSig`. There's extension methods you can use:
+Sometimes you must convert an `ITypeDefOrRef` (`TypeRef`, `TypeDef`, or `TypeSpec`) to/from a `TypeSig`. There's extension methods you can use:
-```csharp
+```C#
// array5 is defined above
ITypeDefOrRef type1 = array5.ToTypeDefOrRef();
TypeSig type2 = type1.ToTypeSig();
@@ -300,22 +297,9 @@ Sometimes you must convert an `ITypeDefOrRef` (`TypeRef`, `TypeDef`, or
Naming conventions of metadata table classes
--------------------------------------------
-For most tables in the metadata, there's a corresponding dnlib class with the
-exact same or a similar name. Eg. the metadata has a `TypeDef` table, and dnlib
-has a `TypeDef` class. Some tables don't have a class because they're
-referenced by other classes, and that information is part of some other class.
-Eg. the `TypeDef` class contains all its properties and events, even though the
-`TypeDef` table has no property or event column.
-
-For each of these table classes, there's an abstract base class, and two sub
-classes. These sub classes are named the same as the base class but ends in
-either `MD` (for classes created from the metadata) or `User` (for classes
-created by the user). Eg. `TypeDef` is the base class, and it has two sub
-classes `TypeDefMD` which is auto-created from metadata, and `TypeRefUser`
-which is created by the user when adding user types. Most of the XyzMD classes
-are internal and can't be referenced directly by the user. They're created by
-`ModuleDefMD` (which is the only public `MD` class). All XyzUser classes are
-public.
+For most tables in the metadata, there's a corresponding dnlib class with the exact same or a similar name. Eg. the metadata has a `TypeDef` table, and dnlib has a `TypeDef` class. Some tables don't have a class because they're referenced by other classes, and that information is part of some other class. Eg. the `TypeDef` class contains all its properties and events, even though the `TypeDef` table has no property or event column.
+
+For each of these table classes, there's an abstract base class, and two sub classes. These sub classes are named the same as the base class but ends in either `MD` (for classes created from the metadata) or `User` (for classes created by the user). Eg. `TypeDef` is the base class, and it has two sub classes `TypeDefMD` which is auto-created from metadata, and `TypeRefUser` which is created by the user when adding user types. Most of the XyzMD classes are internal and can't be referenced directly by the user. They're created by `ModuleDefMD` (which is the only public `MD` class). All XyzUser classes are public.
Metadata table classes
----------------------
@@ -332,23 +316,19 @@ Here's a list of the most common metadata table classes
`GenericParam` is a generic parameter (owned by a `MethodDef` or a `TypeDef`)
-`MemberRef` is what you create if you need a field reference or a method
-reference.
+`MemberRef` is what you create if you need a field reference or a method reference.
-`MethodDef` is a method definition. It usually has a `CilBody` with CIL
-instructions. Owned by a `TypeDef`.
+`MethodDef` is a method definition. It usually has a `CilBody` with CIL instructions. Owned by a `TypeDef`.
`MethodSpec` is a instantiated generic method.
-`ModuleDef` is the base module class. When you read an existing module, a
-`ModuleDefMD` is created.
+`ModuleDef` is the base module class. When you read an existing module, a `ModuleDefMD` is created.
`ModuleRef` is a module reference.
`PropertyDef` is a property definition. Owned by a `TypeDef`.
-`TypeDef` is a type definition. It contains a lot of interesting stuff,
-including methods, fields, properties, etc.
+`TypeDef` is a type definition. It contains a lot of interesting stuff, including methods, fields, properties, etc.
`TypeRef` is a type reference. Usually to a type in another assembly.
@@ -357,31 +337,23 @@ including methods, fields, properties, etc.
Method classes
--------------
-The following are the method classes: `MethodDef`, `MemberRef` (method ref) and
-`MethodSpec`. They all implement `IMethod`.
+The following are the method classes: `MethodDef`, `MemberRef` (method ref) and `MethodSpec`. They all implement `IMethod`.
Field classes
-------------
-The following are the field classes: `FieldDef` and `MemberRef` (field ref).
-They both implement `IField`.
+The following are the field classes: `FieldDef` and `MemberRef` (field ref). They both implement `IField`.
Comparing types, methods, fields, etc
-------------------------------------
-dnlib has a `SigComparer` class that can compare any type with any other type.
-Any method with any other method, etc. It also has several pre-created
-`IEqualityComparer` classes (eg. `TypeEqualityComparer`,
-`FieldEqualityComparer`, etc) which you can use if you intend to eg. use a type
-as a key in a `Dictionary`.
+dnlib has a `SigComparer` class that can compare any type with any other type. Any method with any other method, etc. It also has several pre-created `IEqualityComparer` classes (eg. `TypeEqualityComparer`, `FieldEqualityComparer`, etc) which you can use if you intend to eg. use a type as a key in a `Dictionary`.
-The `SigComparer` class can also compare types with `System.Type`, methods with
-`System.Reflection.MethodBase`, etc.
+The `SigComparer` class can also compare types with `System.Type`, methods with `System.Reflection.MethodBase`, etc.
-It has many options you can set, see `SigComparerOptions`. The default options
-is usually good enough, though.
+It has many options you can set, see `SigComparerOptions`. The default options is usually good enough, though.
-```csharp
+```C#
// Compare two types
TypeRef type1 = ...;
TypeDef type2 = ...;
@@ -404,12 +376,9 @@ It has many `Equals()` and `GetHashCode()` overloads.
.NET Resources
--------------
-There's three types of .NET resource, and they all derive from the common base
-class `Resource`. `ModuleDef.Resources` is a list of all resources the module
-owns.
+There's three types of .NET resource, and they all derive from the common base class `Resource`. `ModuleDef.Resources` is a list of all resources the module owns.
-`EmbeddedResource` is a resource that has data embedded in the owner module.
-This is the most common type of resource and it's probably what you want.
+`EmbeddedResource` is a resource that has data embedded in the owner module. This is the most common type of resource and it's probably what you want.
`AssemblyLinkedResource` is a reference to a resource in another assembly.
@@ -418,74 +387,62 @@ This is the most common type of resource and it's probably what you want.
Win32 resources
---------------
-`ModuleDef.Win32Resources` can be null or a `Win32Resources` instance. You can
-add/remove any Win32 resource blob. dnlib doesn't try to parse these blobs.
+`ModuleDef.Win32Resources` can be null or a `Win32Resources` instance. You can add/remove any Win32 resource blob. dnlib doesn't try to parse these blobs.
Parsing method bodies
---------------------
-This is usually only needed if you have decrypted a method body. If it's a
-standard method body, you can use `MethodBodyReader.Create()`. If it's similar
-to a standard method body, you can derive a class from `MethodBodyReaderBase`
-and override the necessary methods.
+This is usually only needed if you have decrypted a method body. If it's a standard method body, you can use `MethodBodyReader.Create()`. If it's similar to a standard method body, you can derive a class from `MethodBodyReaderBase` and override the necessary methods.
Resolving references
--------------------
-`TypeRef.Resolve()` and `MemberRef.Resolve()` both use
-`module.Context.Resolver` to resolve the type, field or method. The custom
-attribute parser code may also resolve type references.
+`TypeRef.Resolve()` and `MemberRef.Resolve()` both use `module.Context.Resolver` to resolve the type, field or method. The custom attribute parser code may also resolve type references.
-If you call Resolve() or read custom attributes, you should initialize
-module.Context to a `ModuleContext`. It should normally be shared between all
-modules you open.
+If you call `Resolve()` or read custom attributes, you should initialize module.Context to a `ModuleContext`. It should normally be shared between all modules you open.
+
+```C#
+ // You should pass this context to ModuleDefMD.Load(), but you can also write
+ // it to `module.Context`
+ ModuleContext modCtx = ModuleDef.CreateModuleContext();
+ // It creates the default assembly resolver
+ AssemblyResolver asmResolver = (AssemblyResolver)modCtx.AssemblyResolver;
-```csharp
- AssemblyResolver asmResolver = new AssemblyResolver();
- ModuleContext modCtx = new ModuleContext(asmResolver);
-
- // All resolved assemblies will also get this same modCtx
- asmResolver.DefaultModuleContext = modCtx;
-
// Enable the TypeDef cache for all assemblies that are loaded
// by the assembly resolver. Only enable it if all auto-loaded
// assemblies are read-only.
asmResolver.EnableTypeDefCache = true;
```
-All assemblies that you yourself open should be added to the assembly resolver
-cache.
+All assemblies that you yourself open should be added to the assembly resolver cache.
-```csharp
+```C#
ModuleDefMD mod = ModuleDefMD.Load(...);
mod.Context = modCtx; // Use the previously created (and shared) context
- mod.Context.AssemblyResolver.AddToCache(mod);
+ // This code assumes you're using the default assembly resolver
+ ((AssemblyResolver)mod.Context.AssemblyResolver).AddToCache(mod);
```
Resolving types, methods, etc from metadata tokens
--------------------------------------------------
-`ModuleDefMD` has several `ResolveXXX()` methods, eg. `ResolveTypeDef()`,
-`ResolveMethod()`, etc.
+`ModuleDefMD` has several `ResolveXXX()` methods, eg. `ResolveTypeDef()`, `ResolveMethod()`, etc.
Creating mscorlib type references
---------------------------------
-Every module has a `CorLibTypes` property. It has references to a few of the
-simplest types such as all integer types, floating point types, Object, String,
-etc. If you need a type that's not there, you must create it yourself, eg.:
+Every module has a `CorLibTypes` property. It has references to a few of the simplest types such as all integer types, floating point types, Object, String, etc. If you need a type that's not there, you must create it yourself, eg.:
-```csharp
+```C#
TypeRef consoleRef = new TypeRefUser(mod, "System", "Console", mod.CorLibTypes.AssemblyRef);
```
Importing runtime types, methods, fields
----------------------------------------
-To import a `System.Type`, `System.Reflection.MethodInfo`,
-`System.Reflection.FieldInfo`, etc into a module, use the `Importer` class.
+To import a `System.Type`, `System.Reflection.MethodInfo`, `System.Reflection.FieldInfo`, etc into a module, use the `Importer` class.
-```csharp
+```C#
Importer importer = new Importer(mod);
ITypeDefOrRef consoleRef = importer.Import(typeof(System.Console));
IMethod writeLine = importer.Import(typeof(System.Console).GetMethod("WriteLine"));
@@ -493,44 +450,40 @@ To import a `System.Type`, `System.Reflection.MethodInfo`,
You can also use it to import types, methods etc from another `ModuleDef`.
-All imported types, methods etc will be references to the original assembly.
-I.e., it won't add the imported `TypeDef` to the target module. It will just
-create a `TypeRef` to it.
+All imported types, methods etc will be references to the original assembly. I.e., it won't add the imported `TypeDef` to the target module. It will just create a `TypeRef` to it.
Using decrypted methods
-----------------------
-If `ModuleDefMD.MethodDecrypter` is initialized, `ModuleDefMD` will call it and
-check whether the method has been decrypted. If it has, it calls
-`IMethodDecrypter.GetMethodBody()` which you should implement. Return the new
-`MethodBody`. `GetMethodBody()` should usually call `MethodBodyReader.Create()`
-which does the actual parsing of the CIL code.
+If `ModuleDefMD.MethodDecrypter` is initialized, `ModuleDefMD` will call it and check whether the method has been decrypted. If it has, it calls `IMethodDecrypter.GetMethodBody()` which you should implement. Return the new `MethodBody`. `GetMethodBody()` should usually call `MethodBodyReader.Create()` which does the actual parsing of the CIL code.
-It's also possible to override `ModuleDefMD.ReadUserString()`. This method is
-called by the CIL parser when it finds a `Ldstr` instruction. If
-`ModuleDefMD.StringDecrypter` is not null, its `ReadUserString()` method is
-called with the string token. Return the decrypted string or null if it should
-be read from the `#US` heap.
+It's also possible to override `ModuleDefMD.ReadUserString()`. This method is called by the CIL parser when it finds a `Ldstr` instruction. If `ModuleDefMD.StringDecrypter` is not null, its `ReadUserString()` method is called with the string token. Return the decrypted string or null if it should be read from the `#US` heap.
Low level access to the metadata
--------------------------------
The low level classes are in the `dnlib.DotNet.MD` namespace.
-Open an existing .NET module/assembly and you get a ModuleDefMD. It has several
-properties, eg. `StringsStream` is the #Strings stream.
+Open an existing .NET module/assembly and you get a ModuleDefMD. It has several properties, eg. `StringsStream` is the #Strings stream.
-The `MetaData` property gives you full access to the metadata.
+The `Metadata` property gives you full access to the metadata.
To get a list of all valid TypeDef rids (row IDs), use this code:
-```csharp
+```C#
using dnlib.DotNet.MD;
// ...
ModuleDefMD mod = ModuleDefMD.Load(...);
- RidList typeDefRids = mod.MetaData.GetTypeDefRidList();
+ RidList typeDefRids = mod.Metadata.GetTypeDefRidList();
for (int i = 0; i < typeDefRids.Count; i++)
Console.WriteLine("rid: {0}", typeDefRids[i]);
```
-You don't need to create a `ModuleDefMD`, though. See `DotNetFile`.
+You don't need to create a `ModuleDefMD`, though. See `MetadataFactory`.
+
+Credits
+-------
+
+Big thanks to [Ki](https://github.com/yck1509) for writing the managed Windows PDB reader!
+
+[List of all contributors](https://github.com/0xd4d/dnlib/graphs/contributors)
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 000000000..11e20bc0b
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,36 @@
+param([switch]$NoMsbuild)
+
+$ErrorActionPreference = 'Stop'
+
+$configuration = 'Release'
+
+#
+# dotnet build isn't used because it can't build net35 tfms
+#
+
+$env:NoTargetFrameworkNet35 = ''
+
+$useMsbuild = $IsWindows -or $IsWindows -eq $null
+if ($NoMsbuild) {
+ $useMsbuild = $false
+}
+
+if (!$useMsbuild) {
+ # There are currently no net35 reference assemblies on nuget
+ $env:NoTargetFrameworkNet35 = 'true'
+}
+
+if ($useMsbuild) {
+ msbuild -v:m -restore -t:Build -p:Configuration=$configuration
+ if ($LASTEXITCODE) { exit $LASTEXITCODE }
+ msbuild -v:m -t:Pack -p:Configuration=$configuration src/dnlib.csproj
+ if ($LASTEXITCODE) { exit $LASTEXITCODE }
+}
+else {
+ dotnet build -v:m -c $configuration
+ if ($LASTEXITCODE) { exit $LASTEXITCODE }
+ dotnet pack -v:m -c $configuration src/dnlib.csproj
+ if ($LASTEXITCODE) { exit $LASTEXITCODE }
+}
+
+$env:NoTargetFrameworkNet35 = ''
diff --git a/dnlib.sln b/dnlib.sln
index e8dc7640b..cc58351cd 100644
--- a/dnlib.sln
+++ b/dnlib.sln
@@ -1,42 +1,31 @@
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dnlib", "src\dnlib.csproj", "{FDFC1237-143F-4919-8318-4926901F4639}"
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29318.209
+MinimumVisualStudioVersion = 16.0.29318.209
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dnlib", "src\dnlib.csproj", "{FDFC1237-143F-4919-8318-4926901F4639}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples", "Examples\Examples.csproj", "{F27E72B5-C4BD-40BF-AD19-4C8A99B55872}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples", "Examples\Examples.csproj", "{F27E72B5-C4BD-40BF-AD19-4C8A99B55872}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
- Debug|Mixed Platforms = Debug|Mixed Platforms
- Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
- Release|Mixed Platforms = Release|Mixed Platforms
- Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FDFC1237-143F-4919-8318-4926901F4639}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FDFC1237-143F-4919-8318-4926901F4639}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FDFC1237-143F-4919-8318-4926901F4639}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {FDFC1237-143F-4919-8318-4926901F4639}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {FDFC1237-143F-4919-8318-4926901F4639}.Debug|x86.ActiveCfg = Debug|Any CPU
{FDFC1237-143F-4919-8318-4926901F4639}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FDFC1237-143F-4919-8318-4926901F4639}.Release|Any CPU.Build.0 = Release|Any CPU
- {FDFC1237-143F-4919-8318-4926901F4639}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {FDFC1237-143F-4919-8318-4926901F4639}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {FDFC1237-143F-4919-8318-4926901F4639}.Release|x86.ActiveCfg = Release|Any CPU
- {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Debug|Any CPU.ActiveCfg = Debug|x86
- {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
- {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Debug|Mixed Platforms.Build.0 = Debug|x86
- {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Debug|x86.ActiveCfg = Debug|x86
- {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Debug|x86.Build.0 = Debug|x86
- {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Release|Any CPU.ActiveCfg = Release|x86
- {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Release|Mixed Platforms.ActiveCfg = Release|x86
- {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Release|Mixed Platforms.Build.0 = Release|x86
- {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Release|x86.ActiveCfg = Release|x86
- {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Release|x86.Build.0 = Release|x86
+ {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F27E72B5-C4BD-40BF-AD19-4C8A99B55872}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {49902A67-E85B-44E8-9C4F-26F8854AA894}
+ EndGlobalSection
EndGlobal
diff --git a/src/DefaultDllImportSearchPathsAttribute.cs b/src/DefaultDllImportSearchPathsAttribute.cs
new file mode 100644
index 000000000..ad4b10d2a
--- /dev/null
+++ b/src/DefaultDllImportSearchPathsAttribute.cs
@@ -0,0 +1,23 @@
+// dnlib: See LICENSE.txt for more info
+
+#if NET35
+namespace System.Runtime.InteropServices {
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Method, AllowMultiple = false)]
+ sealed class DefaultDllImportSearchPathsAttribute : Attribute {
+ public DefaultDllImportSearchPathsAttribute(DllImportSearchPath paths) => _paths = paths;
+ public DllImportSearchPath Paths => _paths;
+ internal DllImportSearchPath _paths;
+ }
+
+ [Flags]
+ enum DllImportSearchPath {
+ LegacyBehavior = 0,
+ AssemblyDirectory = 2,
+ UseDllDirectoryForDependencies = 0x100,
+ ApplicationDirectory = 0x200,
+ UserDirectories = 0x400,
+ System32 = 0x800,
+ SafeDirectories = 0x1000,
+ }
+}
+#endif
diff --git a/src/DotNet/AccessChecker.cs b/src/DotNet/AccessChecker.cs
deleted file mode 100644
index 3f3758b71..000000000
--- a/src/DotNet/AccessChecker.cs
+++ /dev/null
@@ -1,610 +0,0 @@
-// dnlib: See LICENSE.txt for more info
-
-using System;
-using System.Collections.Generic;
-
-namespace dnlib.DotNet {
- ///
- /// Checks whether a type has access to some other target type, method or field
- /// according to the target's visibility.
- ///
- public struct AccessChecker {
- TypeDef userType;
- List userTypeEnclosingTypes;
- bool enclosingTypesInitialized;
- Dictionary baseTypes;
- bool baseTypesInitialized;
-
- [Flags]
- enum CheckTypeAccess {
- ///
- /// Can't access the type
- ///
- None = 0,
-
- ///
- /// Normal access to the type and its members. Type + member must be public, internal
- /// or protected (for sub classes) to access the member.
- ///
- Normal = 1,
-
- ///
- /// Full access to the type, even if the type is private. If clear, the type
- /// must be public, internal or protected (for sub classes).
- ///
- FullTypeAccess = 2,
-
- ///
- /// Full access to the type's members (types, fields, methods), even if the
- /// members are private. If clear, the members must be public, internal
- /// or protected (for sub classes)
- ///
- FullMemberAccess = 4,
-
- ///
- /// Full access to the type and its members
- ///
- Full = Normal | FullTypeAccess | FullMemberAccess,
- }
-
- ///
- /// Gets/sets the user type which is accessing the target type, field or method
- ///
- public TypeDef UserType {
- get { return userType; }
- set {
- if (userType == value)
- return;
- userType = value;
- enclosingTypesInitialized = false;
- baseTypesInitialized = false;
- if (userTypeEnclosingTypes != null)
- userTypeEnclosingTypes.Clear();
- if (baseTypes != null)
- baseTypes.Clear();
- }
- }
-
- ///
- /// Constructor
- ///
- /// The type accessing the target type, field or method
- public AccessChecker(TypeDef userType) {
- this.userType = userType;
- this.userTypeEnclosingTypes = null;
- this.baseTypes = null;
- this.enclosingTypesInitialized = false;
- this.baseTypesInitialized = false;
- }
-
- ///
- /// Checks whether it can access a method or a field
- ///
- /// Operand
- /// true if it has access to it, false if not, and null
- /// if we can't determine it (eg. we couldn't resolve a type or input was null)
- public bool? CanAccess(object op) {
- var md = op as MethodDef;
- if (md != null)
- return CanAccess(md);
-
- var mr = op as MemberRef;
- if (mr != null)
- return CanAccess(mr);
-
- var fd = op as FieldDef;
- if (fd != null)
- return CanAccess(fd);
-
- var ms = op as MethodSpec;
- if (ms != null)
- return CanAccess(ms);
-
- var tr = op as TypeRef;
- if (tr != null)
- return CanAccess(tr.Resolve());
-
- var td = op as TypeDef;
- if (td != null)
- return CanAccess(td);
-
- var ts = op as TypeSpec;
- if (ts != null)
- return CanAccess(ts);
-
- return null;
- }
-
- ///
- /// Checks whether it can access a
- ///
- /// The type
- /// true if it has access to it, false if not, and null
- /// if we can't determine it (eg. we couldn't resolve a type or input was null)
- public bool? CanAccess(TypeRef tr) {
- if (tr == null)
- return null;
- return CanAccess(tr.Resolve());
- }
-
- ///
- /// Checks whether it can access a
- ///
- /// The type
- /// true if it has access to it, false if not, and null
- /// if we can't determine it (eg. we couldn't resolve a type or input was null)
- public bool? CanAccess(TypeDef td) {
- var access = GetTypeAccess(td, null);
- if (access == null)
- return null;
- return (access.Value & CheckTypeAccess.Normal) != 0;
- }
-
- ///
- /// Returns the access we have to . If is
- /// enclosing this type, we have private access to it and all its members. If its
- /// declaring type encloses us, we have private access to it, but only normal access
- /// to its members. Else, we only have normal access to it and its members. If we inherit
- /// it, we have protected access to it and its members.
- ///
- /// The type
- /// Generic instance of or null if none
- CheckTypeAccess? GetTypeAccess(TypeDef td, GenericInstSig git) {
- if (td == null)
- return null;
- if (userType == td)
- return CheckTypeAccess.Full;
-
- // If this is our nested type, we have private access to it itself, but normal
- // access to its members.
- if (td.DeclaringType == userType)
- return CheckTypeAccess.Normal | CheckTypeAccess.FullTypeAccess;
-
- // If we're not a nested type, td can't be our enclosing type
- if (userType.DeclaringType == null)
- return GetTypeAccess2(td, git);
-
- // Can't be an enclosing type if they're not in the same module
- if (userType.Module != td.Module)
- return GetTypeAccess2(td, git);
-
- var tdEncTypes = GetEnclosingTypes(td, true);
- var ourEncTypes = InitializeOurEnclosingTypes();
- int maxChecks = Math.Min(tdEncTypes.Count, ourEncTypes.Count);
- int commonIndex;
- for (commonIndex = 0; commonIndex < maxChecks; commonIndex++) {
- if (tdEncTypes[commonIndex] != ourEncTypes[commonIndex])
- break;
- }
-
- // If td encloses us, then we have access to td and all its members even if
- // they're private.
- if (commonIndex == tdEncTypes.Count)
- return CheckTypeAccess.Full;
-
- // If there are no common enclosing types, only check the visibility.
- if (commonIndex == 0)
- return GetTypeAccess2(td, git);
-
- // If td's declaring type encloses this, then we have full access to td even if
- // it's private, but only normal access to its members.
- if (commonIndex + 1 == tdEncTypes.Count)
- return CheckTypeAccess.Normal | CheckTypeAccess.FullTypeAccess;
-
- // Normal visibility checks starting from type after common enclosing type.
- // Note that we have full access to it so we don't need to check its access,
- // so start from the next one.
- for (int i = commonIndex + 1; i < tdEncTypes.Count; i++) {
- if (!IsVisible(tdEncTypes[i], null))
- return CheckTypeAccess.None;
- }
- return CheckTypeAccess.Normal;
- }
-
- CheckTypeAccess GetTypeAccess2(TypeDef td, GenericInstSig git) {
- while (td != null) {
- var declType = td.DeclaringType;
- if (userType != declType && !IsVisible(td, git))
- return CheckTypeAccess.None;
- td = declType;
- git = null;
- }
- return CheckTypeAccess.Normal;
- }
-
- ///
- /// Checks whether is visible to us without checking whether they
- /// have any common enclosing types.
- ///
- /// Type
- /// Generic instance of or null if none
- bool IsVisible(TypeDef td, GenericInstSig git) {
- if (td == null)
- return false;
- if (td == userType)
- return true;
-
- switch (td.Visibility) {
- case TypeAttributes.NotPublic:
- return IsSameAssemblyOrFriendAssembly(td.Module);
-
- case TypeAttributes.Public:
- return true;
-
- case TypeAttributes.NestedPublic:
- return true;
-
- case TypeAttributes.NestedPrivate:
- return false;
-
- case TypeAttributes.NestedFamily:
- return CheckFamily(td, git);
-
- case TypeAttributes.NestedAssembly:
- return IsSameAssemblyOrFriendAssembly(td.Module);
-
- case TypeAttributes.NestedFamANDAssem:
- return IsSameAssemblyOrFriendAssembly(td.Module) &&
- CheckFamily(td, git);
-
- case TypeAttributes.NestedFamORAssem:
- return IsSameAssemblyOrFriendAssembly(td.Module) ||
- CheckFamily(td, git);
-
- default:
- return false;
- }
- }
-
- bool IsSameAssemblyOrFriendAssembly(ModuleDef module) {
- if (module == null)
- return false;
- var userModule = userType.Module;
- if (userModule == null)
- return false;
- if (userModule == module)
- return true;
- var userAsm = userModule.Assembly;
- var modAsm = module.Assembly;
- if (IsSameAssembly(userAsm, modAsm))
- return true;
- if (userAsm != null && userAsm.IsFriendAssemblyOf(modAsm))
- return true;
-
- return false;
- }
-
- static bool IsSameAssembly(IAssembly asm1, IAssembly asm2) {
- if (asm1 == null || asm2 == null)
- return false;
- if (asm1 == asm2)
- return true;
- return new AssemblyNameComparer(AssemblyNameComparerFlags.All).Equals(asm1, asm2);
- }
-
- ///
- /// Checks whether has access to .
- /// is Family, FamANDAssem, or FamORAssem.
- ///
- /// Type
- /// Generic instance of or null if none
- bool CheckFamily(TypeDef td, GenericInstSig git) {
- if (td == null)
- return false;
- InitializeBaseTypes();
-
- if (baseTypes.ContainsKey(git == null ? (IType)td : git))
- return true;
-
- // td is Family, FamANDAssem, or FamORAssem. If we derive from its enclosing type,
- // we have access to it.
- var td2 = td.DeclaringType;
- if (td2 != null && baseTypes.ContainsKey(td2))
- return true;
-
- // If one of our enclosing types derive from it, we also have access to it
- var userDeclType = userType.DeclaringType;
- if (userDeclType != null)
- return new AccessChecker(userDeclType).CheckFamily(td, git);
-
- return false;
- }
-
- void InitializeBaseTypes() {
- if (baseTypesInitialized)
- return;
- if (baseTypes == null)
- baseTypes = new Dictionary(TypeEqualityComparer.Instance);
- baseTypesInitialized = true;
-
- ITypeDefOrRef baseType = userType;
- while (baseType != null) {
- baseTypes[baseType] = true;
- baseType = baseType.GetBaseType();
- }
- }
-
- List InitializeOurEnclosingTypes() {
- if (!enclosingTypesInitialized) {
- userTypeEnclosingTypes = GetEnclosingTypes(userType, true);
- enclosingTypesInitialized = true;
- }
- return userTypeEnclosingTypes;
- }
-
- ///
- /// Returns a list of all enclosing types, in order of non-enclosed to most enclosed type
- ///
- /// Type
- /// true if should be included
- /// A list of all enclosing types
- static List GetEnclosingTypes(TypeDef td, bool includeInput) {
- var list = new List();
- if (includeInput && td != null)
- list.Add(td);
- while (td != null) {
- var dt = td.DeclaringType;
- if (dt == null)
- break;
- if (list.Contains(dt))
- break;
- list.Add(dt);
- td = dt;
- }
- list.Reverse();
- return list;
- }
-
- ///
- /// Checks whether it can access a
- ///
- /// The field
- /// true if it has access to it, false if not, and null
- /// if we can't determine it (eg. we couldn't resolve a type or input was null)
- public bool? CanAccess(FieldDef fd) {
- return CanAccess(fd, null);
- }
-
- bool? CanAccess(FieldDef fd, GenericInstSig git) {
- if (fd == null)
- return null;
- var access = GetTypeAccess(fd.DeclaringType, git);
- if (access == null)
- return null;
- var acc = access.Value;
- if ((acc & CheckTypeAccess.Normal) == 0)
- return false;
- if ((acc & CheckTypeAccess.FullMemberAccess) != 0)
- return true;
-
- return IsVisible(fd, git);
- }
-
- bool IsVisible(FieldDef fd, GenericInstSig git) {
- if (fd == null)
- return false;
- var fdDeclaringType = fd.DeclaringType;
- if (fdDeclaringType == null)
- return false;
- if (userType == fdDeclaringType)
- return true;
-
- switch (fd.Access) {
- case FieldAttributes.PrivateScope:
- // Private scope aka compiler controlled fields/methods can only be accessed
- // by a Field/Method token. This means they must be in the same module.
- return userType.Module == fdDeclaringType.Module;
-
- case FieldAttributes.Private:
- return false;
-
- case FieldAttributes.FamANDAssem:
- return IsSameAssemblyOrFriendAssembly(fdDeclaringType.Module) &&
- CheckFamily(fdDeclaringType, git);
-
- case FieldAttributes.Assembly:
- return IsSameAssemblyOrFriendAssembly(fdDeclaringType.Module);
-
- case FieldAttributes.Family:
- return CheckFamily(fdDeclaringType, git);
-
- case FieldAttributes.FamORAssem:
- return IsSameAssemblyOrFriendAssembly(fdDeclaringType.Module) ||
- CheckFamily(fdDeclaringType, git);
-
- case FieldAttributes.Public:
- return true;
-
- default:
- return false;
- }
- }
-
- ///
- /// Checks whether it can access a
- ///
- /// The method
- /// true if it has access to it, false if not, and null
- /// if we can't determine it (eg. we couldn't resolve a type or input was null)
- public bool? CanAccess(MethodDef md) {
- return CanAccess(md, (GenericInstSig)null);
- }
-
- bool? CanAccess(MethodDef md, GenericInstSig git) {
- if (md == null)
- return null;
- var access = GetTypeAccess(md.DeclaringType, git);
- if (access == null)
- return null;
- var acc = access.Value;
- if ((acc & CheckTypeAccess.Normal) == 0)
- return false;
- if ((acc & CheckTypeAccess.FullMemberAccess) != 0)
- return true;
-
- return IsVisible(md, git);
- }
-
- bool IsVisible(MethodDef md, GenericInstSig git) {
- if (md == null)
- return false;
- var mdDeclaringType = md.DeclaringType;
- if (mdDeclaringType == null)
- return false;
- if (userType == mdDeclaringType)
- return true;
-
- switch (md.Access) {
- case MethodAttributes.PrivateScope:
- // Private scope aka compiler controlled fields/methods can only be accessed
- // by a Field/Method token. This means they must be in the same module.
- return userType.Module == mdDeclaringType.Module;
-
- case MethodAttributes.Private:
- return false;
-
- case MethodAttributes.FamANDAssem:
- return IsSameAssemblyOrFriendAssembly(mdDeclaringType.Module) &&
- CheckFamily(mdDeclaringType, git);
-
- case MethodAttributes.Assembly:
- return IsSameAssemblyOrFriendAssembly(mdDeclaringType.Module);
-
- case MethodAttributes.Family:
- return CheckFamily(mdDeclaringType, git);
-
- case MethodAttributes.FamORAssem:
- return IsSameAssemblyOrFriendAssembly(mdDeclaringType.Module) ||
- CheckFamily(mdDeclaringType, git);
-
- case MethodAttributes.Public:
- return true;
-
- default:
- return false;
- }
- }
-
- ///
- /// Checks whether it can access a
- ///
- /// The member reference
- /// true if it has access to it, false if not, and null
- /// if we can't determine it (eg. we couldn't resolve a type or input was null)
- public bool? CanAccess(MemberRef mr) {
- if (mr == null)
- return null;
-
- var parent = mr.Class;
-
- var td = parent as TypeDef;
- if (td != null)
- return CanAccess(td, mr);
-
- var tr = parent as TypeRef;
- if (tr != null)
- return CanAccess(tr.Resolve(), mr);
-
- var ts = parent as TypeSpec;
- if (ts != null)
- return CanAccess(ts.ResolveTypeDef(), ts.TryGetGenericInstSig(), mr);
-
- var md = parent as MethodDef;
- if (md != null)
- return CanAccess(md, mr);
-
- var mod = parent as ModuleRef;
- if (mod != null)
- return CanAccess(mod, mr);
-
- return null;
- }
-
- bool? CanAccess(TypeDef td, MemberRef mr) {
- return CanAccess(td, null, mr);
- }
-
- bool? CanAccess(TypeDef td, GenericInstSig git, MemberRef mr) {
- if (mr == null || td == null)
- return null;
-
- if (mr.MethodSig != null) {
- var md = td.FindMethodCheckBaseType(mr.Name, mr.MethodSig);
- if (md == null) {
- // Assume that it's an array type if it's one of these methods
- if (mr.Name == "Get" || mr.Name == "Set" || mr.Name == "Address" || mr.Name == MethodDef.InstanceConstructorName)
- return true;
- return null;
- }
- return CanAccess(md, git);
- }
-
- if (mr.FieldSig != null)
- return CanAccess(td.FindFieldCheckBaseType(mr.Name, mr.FieldSig), git);
-
- return null;
- }
-
- bool? CanAccess(MethodDef md, MemberRef mr) {
- if (mr == null || md == null)
- return null;
- return CanAccess(md);
- }
-
- bool? CanAccess(ModuleRef mod, MemberRef mr) {
- if (mr == null || mod == null || mod.Module == null)
- return null;
-
- var userModule = userType.Module;
- if (userModule == null)
- return null;
- var userAsm = userModule.Assembly;
- if (!IsSameAssembly(userAsm, mod.Module.Assembly))
- return false;
- if (userAsm == null)
- return false;
- var otherMod = userAsm.FindModule(mod.Name);
- if (otherMod == null)
- return false;
- return CanAccess(otherMod.GlobalType, mr);
- }
-
- ///
- /// Checks whether it can access a
- ///
- /// The type spec
- /// true if it has access to it, false if not, and null
- /// if we can't determine it (eg. we couldn't resolve a type or input was null)
- public bool? CanAccess(TypeSpec ts) {
- return CanAccess(ts.ResolveTypeDef());
- }
-
- ///
- /// Checks whether it can access a
- ///
- /// The method spec
- /// true if it has access to it, false if not, and null
- /// if we can't determine it (eg. we couldn't resolve a type or input was null)
- public bool? CanAccess(MethodSpec ms) {
- if (ms == null)
- return null;
-
- var mdr = ms.Method;
-
- var md = mdr as MethodDef;
- if (md != null)
- return CanAccess(md);
-
- var mr = mdr as MemberRef;
- if (mr != null)
- return CanAccess(mr);
-
- return null;
- }
-
- ///
- public override string ToString() {
- return string.Format("{0}", userType);
- }
- }
-}
diff --git a/src/DotNet/AllTypesHelper.cs b/src/DotNet/AllTypesHelper.cs
index 1d0429ba8..2dcac1f1e 100644
--- a/src/DotNet/AllTypesHelper.cs
+++ b/src/DotNet/AllTypesHelper.cs
@@ -1,13 +1,12 @@
// dnlib: See LICENSE.txt for more info
-using System.Collections.Generic;
-using dnlib.Threading;
+using System.Collections.Generic;
namespace dnlib.DotNet {
///
/// Returns types without getting stuck in an infinite loop
///
- public struct AllTypesHelper {
+ readonly struct AllTypesHelper {
///
/// Gets a list of all types and nested types
///
@@ -15,8 +14,8 @@ public struct AllTypesHelper {
public static IEnumerable Types(IEnumerable types) {
var visited = new Dictionary();
var stack = new Stack>();
- if (types != null)
- stack.Push(types.GetSafeEnumerable().GetEnumerator());
+ if (types is not null)
+ stack.Push(types.GetEnumerator());
while (stack.Count > 0) {
var enumerator = stack.Pop();
while (enumerator.MoveNext()) {
@@ -27,7 +26,7 @@ public static IEnumerable Types(IEnumerable types) {
yield return type;
if (type.NestedTypes.Count > 0) {
stack.Push(enumerator);
- enumerator = type.NestedTypes.GetSafeEnumerable().GetEnumerator();
+ enumerator = type.NestedTypes.GetEnumerator();
}
}
}
diff --git a/src/DotNet/AssemblyAttributes.cs b/src/DotNet/AssemblyAttributes.cs
index 7d2b2dbec..c4a687f43 100644
--- a/src/DotNet/AssemblyAttributes.cs
+++ b/src/DotNet/AssemblyAttributes.cs
@@ -27,6 +27,8 @@ public enum AssemblyAttributes : uint {
PA_AMD64 = 0x0040,
/// Processor Architecture: ARM (PE32)
PA_ARM = 0x0050,
+ /// Processor Architecture: ARM64 (PE32+)
+ PA_ARM64 = 0x0060,
/// applies to any platform but cannot run on any (e.g. reference assembly), should not have "specified" set
PA_NoPlatform = 0x0070,
/// Propagate PA flags to AssemblyRef record
diff --git a/src/DotNet/AssemblyDef.cs b/src/DotNet/AssemblyDef.cs
index bf7636313..109b196d8 100644
--- a/src/DotNet/AssemblyDef.cs
+++ b/src/DotNet/AssemblyDef.cs
@@ -7,51 +7,42 @@
using dnlib.Utils;
using dnlib.DotNet.MD;
using dnlib.DotNet.Writer;
-using dnlib.Threading;
-
-#if THREAD_SAFE
-using ThreadSafe = dnlib.Threading.Collections;
-#else
-using ThreadSafe = System.Collections.Generic;
-#endif
+using System.Text.RegularExpressions;
+using dnlib.DotNet.Pdb;
+using System.Collections.Generic;
+using System.Diagnostics;
namespace dnlib.DotNet {
///
/// A high-level representation of a row in the Assembly table
///
- public abstract class AssemblyDef : IHasCustomAttribute, IHasDeclSecurity, IAssembly, IListListener, ITypeDefFinder, IDnlibDef {
+ public abstract class AssemblyDef : IHasCustomAttribute, IHasDeclSecurity, IHasCustomDebugInformation, IAssembly, IListListener, ITypeDefFinder, IDnlibDef {
///
/// The row id in its table
///
protected uint rid;
///
- public MDToken MDToken {
- get { return new MDToken(Table.Assembly, rid); }
- }
+ public MDToken MDToken => new MDToken(Table.Assembly, rid);
///
public uint Rid {
- get { return rid; }
- set { rid = value; }
+ get => rid;
+ set => rid = value;
}
///
- public int HasCustomAttributeTag {
- get { return 14; }
- }
+ public int HasCustomAttributeTag => 14;
///
- public int HasDeclSecurityTag {
- get { return 2; }
- }
+ public int HasDeclSecurityTag => 2;
///
/// From column Assembly.HashAlgId
///
public AssemblyHashAlgorithm HashAlgorithm {
- get { return hashAlgorithm; }
- set { hashAlgorithm = value; }
+ get => hashAlgorithm;
+ set => hashAlgorithm = value;
}
///
protected AssemblyHashAlgorithm hashAlgorithm;
@@ -62,12 +53,8 @@ public AssemblyHashAlgorithm HashAlgorithm {
///
/// If is null
public Version Version {
- get { return version; }
- set {
- if (value == null)
- throw new ArgumentNullException("value");
- version = value;
- }
+ get => version;
+ set => version = value ?? throw new ArgumentNullException(nameof(value));
}
///
protected Version version;
@@ -76,8 +63,8 @@ public Version Version {
/// From column Assembly.Flags
///
public AssemblyAttributes Attributes {
- get { return (AssemblyAttributes)attributes; }
- set { attributes = (int)value; }
+ get => (AssemblyAttributes)attributes;
+ set => attributes = (int)value;
}
/// Attributes
protected int attributes;
@@ -87,8 +74,8 @@ public AssemblyAttributes Attributes {
///
/// An empty is created if the caller writes null
public PublicKey PublicKey {
- get { return publicKey; }
- set { publicKey = value ?? new PublicKey(); }
+ get => publicKey;
+ set => publicKey = value ?? new PublicKey();
}
///
protected PublicKey publicKey;
@@ -96,16 +83,14 @@ public PublicKey PublicKey {
///
/// Gets the public key token which is calculated from
///
- public PublicKeyToken PublicKeyToken {
- get { return publicKey.Token; }
- }
+ public PublicKeyToken PublicKeyToken => publicKey.Token;
///
/// From column Assembly.Name
///
public UTF8String Name {
- get { return name; }
- set { name = value; }
+ get => name;
+ set => name = value;
}
/// Name
protected UTF8String name;
@@ -114,48 +99,41 @@ public UTF8String Name {
/// From column Assembly.Locale
///
public UTF8String Culture {
- get { return culture; }
- set { culture = value; }
+ get => culture;
+ set => culture = value;
}
/// Name
protected UTF8String culture;
///
- public ThreadSafe.IList DeclSecurities {
+ public IList DeclSecurities {
get {
- if (declSecurities == null)
+ if (declSecurities is null)
InitializeDeclSecurities();
return declSecurities;
}
}
///
- protected ThreadSafe.IList declSecurities;
+ protected IList declSecurities;
/// Initializes
- protected virtual void InitializeDeclSecurities() {
- Interlocked.CompareExchange(ref declSecurities, ThreadSafeListCreator.Create(), null);
- }
+ protected virtual void InitializeDeclSecurities() =>
+ Interlocked.CompareExchange(ref declSecurities, new List(), null);
///
- public PublicKeyBase PublicKeyOrToken {
- get { return publicKey; }
- }
+ public PublicKeyBase PublicKeyOrToken => publicKey;
///
- public string FullName {
- get { return GetFullNameWithPublicKeyToken(); }
- }
+ public string FullName => GetFullNameWithPublicKeyToken();
///
- public string FullNameToken {
- get { return GetFullNameWithPublicKeyToken(); }
- }
+ public string FullNameToken => GetFullNameWithPublicKeyToken();
///
/// Gets all modules. The first module is always the .
///
- public ThreadSafe.IList Modules {
+ public IList Modules {
get {
- if (modules == null)
+ if (modules is null)
InitializeModules();
return modules;
}
@@ -163,16 +141,15 @@ public ThreadSafe.IList Modules {
///
protected LazyList modules;
/// Initializes
- protected virtual void InitializeModules() {
+ protected virtual void InitializeModules() =>
Interlocked.CompareExchange(ref modules, new LazyList(this), null);
- }
///
/// Gets all custom attributes
///
public CustomAttributeCollection CustomAttributes {
get {
- if (customAttributes == null)
+ if (customAttributes is null)
InitializeCustomAttributes();
return customAttributes;
}
@@ -180,34 +157,47 @@ public CustomAttributeCollection CustomAttributes {
///
protected CustomAttributeCollection customAttributes;
/// Initializes
- protected virtual void InitializeCustomAttributes() {
+ protected virtual void InitializeCustomAttributes() =>
Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null);
- }
///
- public bool HasCustomAttributes {
- get { return CustomAttributes.Count > 0; }
- }
+ public bool HasCustomAttributes => CustomAttributes.Count > 0;
+
+
+ ///
+ public int HasCustomDebugInformationTag => 14;
///
- public bool HasDeclSecurities {
- get { return DeclSecurities.Count > 0; }
+ public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0;
+
+ ///
+ /// Gets all custom debug infos
+ ///
+ public IList CustomDebugInfos {
+ get {
+ if (customDebugInfos is null)
+ InitializeCustomDebugInfos();
+ return customDebugInfos;
+ }
}
+ ///
+ protected IList customDebugInfos;
+ /// Initializes
+ protected virtual void InitializeCustomDebugInfos() =>
+ Interlocked.CompareExchange(ref customDebugInfos, new List(), null);
+ ///
+ public bool HasDeclSecurities => DeclSecurities.Count > 0;
///
/// true if is not empty
///
- public bool HasModules {
- get { return Modules.Count > 0; }
- }
+ public bool HasModules => Modules.Count > 0;
///
/// Gets the manifest (main) module. This is always the first module in .
/// null is returned if is empty.
///
- public ModuleDef ManifestModule {
- get { return Modules.Get(0, null); }
- }
+ public ModuleDef ManifestModule => Modules.Count == 0 ? null : Modules[0];
///
/// Modify property: =
@@ -215,17 +205,8 @@ public ModuleDef ManifestModule {
///
/// Value to AND
/// Value to OR
- void ModifyAttributes(AssemblyAttributes andMask, AssemblyAttributes orMask) {
-#if THREAD_SAFE
- int origVal, newVal;
- do {
- origVal = attributes;
- newVal = (origVal & (int)andMask) | (int)orMask;
- } while (Interlocked.CompareExchange(ref attributes, newVal, origVal) != origVal);
-#else
+ void ModifyAttributes(AssemblyAttributes andMask, AssemblyAttributes orMask) =>
attributes = (attributes & (int)andMask) | (int)orMask;
-#endif
- }
///
/// Set or clear flags in
@@ -234,149 +215,120 @@ void ModifyAttributes(AssemblyAttributes andMask, AssemblyAttributes orMask) {
/// be cleared
/// Flags to set or clear
void ModifyAttributes(bool set, AssemblyAttributes flags) {
-#if THREAD_SAFE
- int origVal, newVal;
- do {
- origVal = attributes;
- if (set)
- newVal = origVal | (int)flags;
- else
- newVal = origVal & ~(int)flags;
- } while (Interlocked.CompareExchange(ref attributes, newVal, origVal) != origVal);
-#else
if (set)
attributes |= (int)flags;
else
attributes &= ~(int)flags;
-#endif
}
///
/// Gets/sets the bit
///
public bool HasPublicKey {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PublicKey) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.PublicKey); }
+ get => ((AssemblyAttributes)attributes & AssemblyAttributes.PublicKey) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.PublicKey);
}
///
/// Gets/sets the processor architecture
///
public AssemblyAttributes ProcessorArchitecture {
- get { return (AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask; }
- set { ModifyAttributes(~AssemblyAttributes.PA_Mask, value & AssemblyAttributes.PA_Mask); }
+ get => (AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask;
+ set => ModifyAttributes(~AssemblyAttributes.PA_Mask, value & AssemblyAttributes.PA_Mask);
}
///
/// Gets/sets the processor architecture
///
public AssemblyAttributes ProcessorArchitectureFull {
- get { return (AssemblyAttributes)attributes & AssemblyAttributes.PA_FullMask; }
- set { ModifyAttributes(~AssemblyAttributes.PA_FullMask, value & AssemblyAttributes.PA_FullMask); }
+ get => (AssemblyAttributes)attributes & AssemblyAttributes.PA_FullMask;
+ set => ModifyAttributes(~AssemblyAttributes.PA_FullMask, value & AssemblyAttributes.PA_FullMask);
}
///
/// true if unspecified processor architecture
///
- public bool IsProcessorArchitectureNone {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_None; }
- }
+ public bool IsProcessorArchitectureNone => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_None;
///
/// true if neutral (PE32) architecture
///
- public bool IsProcessorArchitectureMSIL {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_MSIL; }
- }
+ public bool IsProcessorArchitectureMSIL => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_MSIL;
///
/// true if x86 (PE32) architecture
///
- public bool IsProcessorArchitectureX86 {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_x86; }
- }
+ public bool IsProcessorArchitectureX86 => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_x86;
///
/// true if IA-64 (PE32+) architecture
///
- public bool IsProcessorArchitectureIA64 {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_IA64; }
- }
+ public bool IsProcessorArchitectureIA64 => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_IA64;
///
/// true if x64 (PE32+) architecture
///
- public bool IsProcessorArchitectureX64 {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_AMD64; }
- }
+ public bool IsProcessorArchitectureX64 => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_AMD64;
///
/// true if ARM (PE32) architecture
///
- public bool IsProcessorArchitectureARM {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_ARM; }
- }
+ public bool IsProcessorArchitectureARM => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_ARM;
///
/// true if eg. reference assembly (not runnable)
///
- public bool IsProcessorArchitectureNoPlatform {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_NoPlatform; }
- }
+ public bool IsProcessorArchitectureNoPlatform => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_NoPlatform;
///
/// Gets/sets the bit
///
public bool IsProcessorArchitectureSpecified {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Specified) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.PA_Specified); }
+ get => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Specified) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.PA_Specified);
}
///
/// Gets/sets the bit
///
public bool EnableJITcompileTracking {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.EnableJITcompileTracking) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.EnableJITcompileTracking); }
+ get => ((AssemblyAttributes)attributes & AssemblyAttributes.EnableJITcompileTracking) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.EnableJITcompileTracking);
}
///
/// Gets/sets the bit
///
public bool DisableJITcompileOptimizer {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.DisableJITcompileOptimizer) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.DisableJITcompileOptimizer); }
+ get => ((AssemblyAttributes)attributes & AssemblyAttributes.DisableJITcompileOptimizer) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.DisableJITcompileOptimizer);
}
///
/// Gets/sets the bit
///
public bool IsRetargetable {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.Retargetable) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.Retargetable); }
+ get => ((AssemblyAttributes)attributes & AssemblyAttributes.Retargetable) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.Retargetable);
}
///
/// Gets/sets the content type
///
public AssemblyAttributes ContentType {
- get { return (AssemblyAttributes)attributes & AssemblyAttributes.ContentType_Mask; }
- set { ModifyAttributes(~AssemblyAttributes.ContentType_Mask, value & AssemblyAttributes.ContentType_Mask); }
+ get => (AssemblyAttributes)attributes & AssemblyAttributes.ContentType_Mask;
+ set => ModifyAttributes(~AssemblyAttributes.ContentType_Mask, value & AssemblyAttributes.ContentType_Mask);
}
///
/// true if content type is Default
///
- public bool IsContentTypeDefault {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_Default; }
- }
+ public bool IsContentTypeDefault => ((AssemblyAttributes)attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_Default;
///
/// true if content type is WindowsRuntime
///
- public bool IsContentTypeWindowsRuntime {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_WindowsRuntime; }
- }
+ public bool IsContentTypeWindowsRuntime => ((AssemblyAttributes)attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_WindowsRuntime;
///
/// Finds a module in this assembly
@@ -384,8 +336,11 @@ public bool IsContentTypeWindowsRuntime {
/// Name of module
/// A instance or null if it wasn't found.
public ModuleDef FindModule(UTF8String name) {
- foreach (var module in Modules.GetSafeEnumerable()) {
- if (module == null)
+ var modules = Modules;
+ int count = modules.Count;
+ for (int i = 0; i < count; i++) {
+ var module = modules[i];
+ if (module is null)
continue;
if (UTF8String.CaseInsensitiveEquals(module.Name, name))
return module;
@@ -393,17 +348,6 @@ public ModuleDef FindModule(UTF8String name) {
return null;
}
- ///
- /// Creates an instance from a file
- ///
- /// File name of an existing .NET assembly
- /// A new instance
- /// If is null
- /// If it's not a .NET assembly (eg. not a .NET file or only a .NET module)
- public static AssemblyDef Load(string fileName) {
- return Load(fileName, (ModuleCreationOptions)null);
- }
-
///
/// Creates an instance from a file
///
@@ -412,9 +356,8 @@ public static AssemblyDef Load(string fileName) {
/// A new instance
/// If is null
/// If it's not a .NET assembly (eg. not a .NET file or only a .NET module)
- public static AssemblyDef Load(string fileName, ModuleContext context) {
- return Load(fileName, new ModuleCreationOptions(context));
- }
+ public static AssemblyDef Load(string fileName, ModuleContext context) =>
+ Load(fileName, new ModuleCreationOptions(context));
///
/// Creates an instance from a file
@@ -424,35 +367,24 @@ public static AssemblyDef Load(string fileName, ModuleContext context) {
/// A new instance
/// If is null
/// If it's not a .NET assembly (eg. not a .NET file or only a .NET module)
- public static AssemblyDef Load(string fileName, ModuleCreationOptions options) {
- if (fileName == null)
- throw new ArgumentNullException("fileName");
+ public static AssemblyDef Load(string fileName, ModuleCreationOptions options = null) {
+ if (fileName is null)
+ throw new ArgumentNullException(nameof(fileName));
ModuleDef module = null;
try {
module = ModuleDefMD.Load(fileName, options);
var asm = module.Assembly;
- if (asm == null)
- throw new BadImageFormatException(string.Format("{0} is only a .NET module, not a .NET assembly. Use ModuleDef.Load().", fileName));
+ if (asm is null)
+ throw new BadImageFormatException($"{fileName} is only a .NET module, not a .NET assembly. Use ModuleDef.Load().");
return asm;
}
catch {
- if (module != null)
+ if (module is not null)
module.Dispose();
throw;
}
}
- ///
- /// Creates an instance from a byte[]
- ///
- /// Contents of a .NET assembly
- /// A new instance
- /// If is null
- /// If it's not a .NET assembly (eg. not a .NET file or only a .NET module)
- public static AssemblyDef Load(byte[] data) {
- return Load(data, (ModuleCreationOptions)null);
- }
-
///
/// Creates an instance from a byte[]
///
@@ -461,9 +393,8 @@ public static AssemblyDef Load(byte[] data) {
/// A new instance
/// If is null
/// If it's not a .NET assembly (eg. not a .NET file or only a .NET module)
- public static AssemblyDef Load(byte[] data, ModuleContext context) {
- return Load(data, new ModuleCreationOptions(context));
- }
+ public static AssemblyDef Load(byte[] data, ModuleContext context) =>
+ Load(data, new ModuleCreationOptions(context));
///
/// Creates an instance from a byte[]
@@ -473,35 +404,24 @@ public static AssemblyDef Load(byte[] data, ModuleContext context) {
/// A new instance
/// If is null
/// If it's not a .NET assembly (eg. not a .NET file or only a .NET module)
- public static AssemblyDef Load(byte[] data, ModuleCreationOptions options) {
- if (data == null)
- throw new ArgumentNullException("data");
+ public static AssemblyDef Load(byte[] data, ModuleCreationOptions options = null) {
+ if (data is null)
+ throw new ArgumentNullException(nameof(data));
ModuleDef module = null;
try {
module = ModuleDefMD.Load(data, options);
var asm = module.Assembly;
- if (asm == null)
- throw new BadImageFormatException(string.Format("{0} is only a .NET module, not a .NET assembly. Use ModuleDef.Load().", module.ToString()));
+ if (asm is null)
+ throw new BadImageFormatException($"{module.ToString()} is only a .NET module, not a .NET assembly. Use ModuleDef.Load().");
return asm;
}
catch {
- if (module != null)
+ if (module is not null)
module.Dispose();
throw;
}
}
- ///
- /// Creates an instance from a memory location
- ///
- /// Address of a .NET assembly
- /// A new instance
- /// If is null
- /// If it's not a .NET assembly (eg. not a .NET file or only a .NET module)
- public static AssemblyDef Load(IntPtr addr) {
- return Load(addr, (ModuleCreationOptions)null);
- }
-
///
/// Creates an instance from a memory location
///
@@ -510,9 +430,8 @@ public static AssemblyDef Load(IntPtr addr) {
/// A new instance
/// If is null
/// If it's not a .NET assembly (eg. not a .NET file or only a .NET module)
- public static AssemblyDef Load(IntPtr addr, ModuleContext context) {
- return Load(addr, new ModuleCreationOptions(context));
- }
+ public static AssemblyDef Load(IntPtr addr, ModuleContext context) =>
+ Load(addr, new ModuleCreationOptions(context));
///
/// Creates an instance from a memory location
@@ -522,37 +441,24 @@ public static AssemblyDef Load(IntPtr addr, ModuleContext context) {
/// A new instance
/// If is null
/// If it's not a .NET assembly (eg. not a .NET file or only a .NET module)
- public static AssemblyDef Load(IntPtr addr, ModuleCreationOptions options) {
+ public static AssemblyDef Load(IntPtr addr, ModuleCreationOptions options = null) {
if (addr == IntPtr.Zero)
- throw new ArgumentNullException("addr");
+ throw new ArgumentNullException(nameof(addr));
ModuleDef module = null;
try {
module = ModuleDefMD.Load(addr, options);
var asm = module.Assembly;
- if (asm == null)
- throw new BadImageFormatException(string.Format("{0} (addr: {1:X8}) is only a .NET module, not a .NET assembly. Use ModuleDef.Load().", module.ToString(), addr.ToInt64()));
+ if (asm is null)
+ throw new BadImageFormatException($"{module.ToString()} (addr: {addr.ToInt64():X8}) is only a .NET module, not a .NET assembly. Use ModuleDef.Load().");
return asm;
}
catch {
- if (module != null)
+ if (module is not null)
module.Dispose();
throw;
}
}
- ///
- /// Creates an instance from a stream
- ///
- /// This will read all bytes from the stream and call .
- /// It's better to use one of the other Load() methods.
- /// The stream
- /// A new instance
- /// If is null
- /// If it's not a .NET assembly (eg. not a .NET file or only a .NET module)
- public static AssemblyDef Load(Stream stream) {
- return Load(stream, (ModuleCreationOptions)null);
- }
-
///
/// Creates an instance from a stream
///
@@ -563,9 +469,8 @@ public static AssemblyDef Load(Stream stream) {
/// A new instance
/// If is null
/// If it's not a .NET assembly (eg. not a .NET file or only a .NET module)
- public static AssemblyDef Load(Stream stream, ModuleContext context) {
- return Load(stream, new ModuleCreationOptions(context));
- }
+ public static AssemblyDef Load(Stream stream, ModuleContext context) =>
+ Load(stream, new ModuleCreationOptions(context));
///
/// Creates an instance from a stream
@@ -577,19 +482,19 @@ public static AssemblyDef Load(Stream stream, ModuleContext context) {
/// A new instance
/// If is null
/// If it's not a .NET assembly (eg. not a .NET file or only a .NET module)
- public static AssemblyDef Load(Stream stream, ModuleCreationOptions options) {
- if (stream == null)
- throw new ArgumentNullException("stream");
+ public static AssemblyDef Load(Stream stream, ModuleCreationOptions options = null) {
+ if (stream is null)
+ throw new ArgumentNullException(nameof(stream));
ModuleDef module = null;
try {
module = ModuleDefMD.Load(stream, options);
var asm = module.Assembly;
- if (asm == null)
- throw new BadImageFormatException(string.Format("{0} is only a .NET module, not a .NET assembly. Use ModuleDef.Load().", module.ToString()));
+ if (asm is null)
+ throw new BadImageFormatException($"{module.ToString()} is only a .NET module, not a .NET assembly. Use ModuleDef.Load().");
return asm;
}
catch {
- if (module != null)
+ if (module is not null)
module.Dispose();
throw;
}
@@ -598,20 +503,12 @@ public static AssemblyDef Load(Stream stream, ModuleCreationOptions options) {
///
/// Gets the assembly name with the public key
///
- public string GetFullNameWithPublicKey() {
- return GetFullName(publicKey);
- }
+ public string GetFullNameWithPublicKey() => FullNameFactory.AssemblyFullName(this, false);
///
/// Gets the assembly name with the public key token
///
- public string GetFullNameWithPublicKeyToken() {
- return GetFullName(publicKey.Token);
- }
-
- string GetFullName(PublicKeyBase pkBase) {
- return Utils.GetAssemblyNameString(name, version, culture, pkBase, Attributes);
- }
+ public string GetFullNameWithPublicKeyToken() => FullNameFactory.AssemblyFullName(this, true);
///
/// Finds a . For speed, enable
@@ -623,11 +520,14 @@ string GetFullName(PublicKeyBase pkBase) {
/// are separated by a / character.
/// An existing or null if it wasn't found.
public TypeDef Find(string fullName, bool isReflectionName) {
- foreach (var module in Modules.GetSafeEnumerable()) {
- if (module == null)
+ var modules = Modules;
+ int count = modules.Count;
+ for (int i = 0; i < count; i++) {
+ var module = modules[i];
+ if (module is null)
continue;
var type = module.Find(fullName, isReflectionName);
- if (type != null)
+ if (type is not null)
return type;
}
return null;
@@ -641,56 +541,41 @@ public TypeDef Find(string fullName, bool isReflectionName) {
/// The type ref
/// An existing or null if it wasn't found.
public TypeDef Find(TypeRef typeRef) {
- foreach (var module in Modules.GetSafeEnumerable()) {
- if (module == null)
+ var modules = Modules;
+ int count = modules.Count;
+ for (int i = 0; i < count; i++) {
+ var module = modules[i];
+ if (module is null)
continue;
var type = module.Find(typeRef);
- if (type != null)
+ if (type is not null)
return type;
}
return null;
}
- ///
- /// Writes the assembly to a file on disk. If the file exists, it will be truncated.
- ///
- /// Filename
- public void Write(string filename) {
- Write(filename, null);
- }
-
///
/// Writes the assembly to a file on disk. If the file exists, it will be truncated.
///
/// Filename
/// Writer options
- public void Write(string filename, ModuleWriterOptions options) {
+ public void Write(string filename, ModuleWriterOptions options = null) =>
ManifestModule.Write(filename, options);
- }
-
- ///
- /// Writes the assembly to a stream.
- ///
- /// Destination stream
- public void Write(Stream dest) {
- Write(dest, null);
- }
///
/// Writes the assembly to a stream.
///
/// Destination stream
/// Writer options
- public void Write(Stream dest, ModuleWriterOptions options) {
+ public void Write(Stream dest, ModuleWriterOptions options = null) =>
ManifestModule.Write(dest, options);
- }
///
/// Checks whether this assembly is a friend assembly of
///
/// Target assembly
public bool IsFriendAssemblyOf(AssemblyDef targetAsm) {
- if (targetAsm == null)
+ if (targetAsm is null)
return false;
if (this == targetAsm)
return true;
@@ -703,7 +588,7 @@ public bool IsFriendAssemblyOf(AssemblyDef targetAsm) {
foreach (var ca in targetAsm.CustomAttributes.FindAll("System.Runtime.CompilerServices.InternalsVisibleToAttribute")) {
if (ca.ConstructorArguments.Count != 1)
continue;
- var arg = ca.ConstructorArguments.Get(0, default(CAArgument));
+ var arg = ca.ConstructorArguments.Count == 0 ? default : ca.ConstructorArguments[0];
if (arg.Type.GetElementType() != ElementType.String)
continue;
var asmName = arg.Value as UTF8String;
@@ -736,23 +621,20 @@ public bool IsFriendAssemblyOf(AssemblyDef targetAsm) {
/// Signature public key
public void UpdateOrCreateAssemblySignatureKeyAttribute(StrongNamePublicKey identityPubKey, StrongNameKey identityKey, StrongNamePublicKey signaturePubKey) {
var manifestModule = ManifestModule;
- if (manifestModule == null)
+ if (manifestModule is null)
return;
// Remove all existing attributes
- var ca = CustomAttributes.ExecuteLocked(null, (tsList, arg) => {
- CustomAttribute foundCa = null;
- for (int i = 0; i < tsList.Count_NoLock(); i++) {
- var caTmp = tsList.Get_NoLock(i);
- if (caTmp.TypeFullName != "System.Reflection.AssemblySignatureKeyAttribute")
- continue;
- tsList.RemoveAt_NoLock(i);
- i--;
- if (foundCa == null)
- foundCa = caTmp;
- }
- return foundCa;
- });
+ CustomAttribute ca = null;
+ for (int i = 0; i < CustomAttributes.Count; i++) {
+ var caTmp = CustomAttributes[i];
+ if (caTmp.TypeFullName != "System.Reflection.AssemblySignatureKeyAttribute")
+ continue;
+ CustomAttributes.RemoveAt(i);
+ i--;
+ if (ca is null)
+ ca = caTmp;
+ }
if (IsValidAssemblySignatureKeyAttribute(ca))
ca.NamedArguments.Clear();
@@ -766,16 +648,15 @@ public void UpdateOrCreateAssemblySignatureKeyAttribute(StrongNamePublicKey iden
}
bool IsValidAssemblySignatureKeyAttribute(CustomAttribute ca) {
-#if THREAD_SAFE
- return false;
-#else
- if (ca == null)
+ if (dnlib.Settings.IsThreadSafe)
+ return false;
+ if (ca is null)
return false;
var ctor = ca.Constructor;
- if (ctor == null)
+ if (ctor is null)
return false;
var sig = ctor.MethodSig;
- if (sig == null || sig.Params.Count != 2)
+ if (sig is null || sig.Params.Count != 2)
return false;
if (sig.Params[0].GetElementType() != ElementType.String)
return false;
@@ -784,7 +665,6 @@ bool IsValidAssemblySignatureKeyAttribute(CustomAttribute ca) {
if (ca.ConstructorArguments.Count != 2)
return false;
return true;
-#endif
}
CustomAttribute CreateAssemblySignatureKeyAttribute() {
@@ -798,28 +678,44 @@ CustomAttribute CreateAssemblySignatureKeyAttribute() {
return ca;
}
+ ///
+ /// Gets the original System.Runtime.Versioning.TargetFrameworkAttribute custom attribute information if possible.
+ /// It reads this from the original metadata and doesn't use .
+ /// Returns false if the custom attribute isn't present or if it is invalid.
+ ///
+ /// Framework name
+ /// Version
+ /// Profile
+ ///
+ public virtual bool TryGetOriginalTargetFrameworkAttribute(out string framework, out Version version, out string profile) {
+ framework = null;
+ version = null;
+ profile = null;
+ return false;
+ }
+
///
void IListListener.OnLazyAdd(int index, ref ModuleDef module) {
- if (module == null)
+ if (module is null)
return;
#if DEBUG
- if (module.Assembly == null)
- throw new InvalidOperationException("Module.Assembly == null");
+ if (module.Assembly is null)
+ throw new InvalidOperationException("Module.Assembly is null");
#endif
}
///
void IListListener.OnAdd(int index, ModuleDef module) {
- if (module == null)
+ if (module is null)
return;
- if (module.Assembly != null)
+ if (module.Assembly is not null)
throw new InvalidOperationException("Module already has an assembly. Remove it from that assembly before adding it to this assembly.");
module.Assembly = this;
}
///
void IListListener.OnRemove(int index, ModuleDef module) {
- if (module != null)
+ if (module is not null)
module.Assembly = null;
}
@@ -829,16 +725,14 @@ void IListListener.OnResize(int index) {
///
void IListListener.OnClear() {
- foreach (var module in Modules.GetEnumerable_NoLock()) {
- if (module != null)
+ foreach (var module in modules.GetEnumerable_NoLock()) {
+ if (module is not null)
module.Assembly = null;
}
}
///
- public override string ToString() {
- return FullName;
- }
+ public override string ToString() => FullName;
}
///
@@ -891,18 +785,16 @@ public AssemblyDefUser(UTF8String name, Version version, PublicKey publicKey)
/// Locale
/// If any of the args is invalid
public AssemblyDefUser(UTF8String name, Version version, PublicKey publicKey, UTF8String locale) {
- if ((object)name == null)
- throw new ArgumentNullException("name");
- if (version == null)
- throw new ArgumentNullException("version");
- if ((object)locale == null)
- throw new ArgumentNullException("locale");
- this.modules = new LazyList(this);
+ if (name is null)
+ throw new ArgumentNullException(nameof(name));
+ if (locale is null)
+ throw new ArgumentNullException(nameof(locale));
+ modules = new LazyList(this);
this.name = name;
- this.version = version;
+ this.version = version ?? throw new ArgumentNullException(nameof(version));
this.publicKey = publicKey ?? new PublicKey();
- this.culture = locale;
- this.attributes = (int)AssemblyAttributes.None;
+ culture = locale;
+ attributes = (int)AssemblyAttributes.None;
}
///
@@ -912,8 +804,8 @@ public AssemblyDefUser(UTF8String name, Version version, PublicKey publicKey, UT
/// If is null
public AssemblyDefUser(AssemblyName asmName)
: this(new AssemblyNameInfo(asmName)) {
- this.hashAlgorithm = (AssemblyHashAlgorithm)asmName.HashAlgorithm;
- this.attributes = (int)asmName.Flags;
+ hashAlgorithm = (AssemblyHashAlgorithm)asmName.HashAlgorithm;
+ attributes = (int)asmName.Flags;
}
///
@@ -922,15 +814,15 @@ public AssemblyDefUser(AssemblyName asmName)
/// Assembly name info
/// If is null
public AssemblyDefUser(IAssembly asmName) {
- if (asmName == null)
- throw new ArgumentNullException("asmName");
- this.modules = new LazyList(this);
- this.name = asmName.Name;
- this.version = asmName.Version ?? new Version(0, 0, 0, 0);
- this.publicKey = asmName.PublicKeyOrToken as PublicKey ?? new PublicKey();
- this.culture = asmName.Culture;
- this.attributes = (int)AssemblyAttributes.None;
- this.hashAlgorithm = AssemblyHashAlgorithm.SHA1;
+ if (asmName is null)
+ throw new ArgumentNullException(nameof(asmName));
+ modules = new LazyList(this);
+ name = asmName.Name;
+ version = asmName.Version ?? new Version(0, 0, 0, 0);
+ publicKey = asmName.PublicKeyOrToken as PublicKey ?? new PublicKey();
+ culture = asmName.Culture;
+ attributes = (int)AssemblyAttributes.None;
+ hashAlgorithm = AssemblyHashAlgorithm.SHA1;
}
}
@@ -944,27 +836,25 @@ sealed class AssemblyDefMD : AssemblyDef, IMDTokenProviderMD {
readonly uint origRid;
///
- public uint OrigRid {
- get { return origRid; }
- }
+ public uint OrigRid => origRid;
///
protected override void InitializeDeclSecurities() {
- var list = readerModule.MetaData.GetDeclSecurityRidList(Table.Assembly, origRid);
- var tmp = new LazyList((int)list.Length, list, (list2, index) => readerModule.ResolveDeclSecurity(((RidList)list2)[index]));
+ var list = readerModule.Metadata.GetDeclSecurityRidList(Table.Assembly, origRid);
+ var tmp = new LazyList(list.Count, list, (list2, index) => readerModule.ResolveDeclSecurity(list2[index]));
Interlocked.CompareExchange(ref declSecurities, tmp, null);
}
///
protected override void InitializeModules() {
var list = readerModule.GetModuleRidList();
- var tmp = new LazyList((int)list.Length + 1, this, list, (list2, index) => {
+ var tmp = new LazyList(list.Count + 1, this, list, (list2, index) => {
ModuleDef module;
if (index == 0)
module = readerModule;
else
- module = readerModule.ReadModule(((RidList)list2)[index - 1], this);
- if (module == null)
+ module = readerModule.ReadModule(list2[index - 1], this);
+ if (module is null)
module = new ModuleDefUser("INVALID", Guid.NewGuid());
module.Assembly = this;
return module;
@@ -974,11 +864,175 @@ protected override void InitializeModules() {
///
protected override void InitializeCustomAttributes() {
- var list = readerModule.MetaData.GetCustomAttributeRidList(Table.Assembly, origRid);
- var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index]));
+ var list = readerModule.Metadata.GetCustomAttributeRidList(Table.Assembly, origRid);
+ var tmp = new CustomAttributeCollection(list.Count, list, (list2, index) => readerModule.ReadCustomAttribute(list[index]));
Interlocked.CompareExchange(ref customAttributes, tmp, null);
}
+ ///
+ protected override void InitializeCustomDebugInfos() {
+ var list = new List();
+ readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(), list);
+ Interlocked.CompareExchange(ref customDebugInfos, list, null);
+ }
+
+ ///
+ public override bool TryGetOriginalTargetFrameworkAttribute(out string framework, out Version version, out string profile) {
+ if (!hasInitdTFA)
+ InitializeTargetFrameworkAttribute();
+ framework = tfaFramework;
+ version = tfaVersion;
+ profile = tfaProfile;
+ return tfaReturnValue;
+ }
+ volatile bool hasInitdTFA;
+ string tfaFramework;
+ Version tfaVersion;
+ string tfaProfile;
+ bool tfaReturnValue;
+
+ void InitializeTargetFrameworkAttribute() {
+ if (hasInitdTFA)
+ return;
+
+ var list = readerModule.Metadata.GetCustomAttributeRidList(Table.Assembly, origRid);
+ var gpContext = new GenericParamContext();
+ for (int i = 0; i < list.Count; i++) {
+ var caRid = list[i];
+ if (!readerModule.TablesStream.TryReadCustomAttributeRow(caRid, out var caRow))
+ continue;
+
+ // Prevent a possible infinite loop.
+ // This can happen when a custom AssemblyResolver calls this function when resolving an AssemblyRef.
+ // If this function encounters a custom attribute whose type is a MemberRef with a TypeSpec class,
+ // the MemberRef constructor called by ResolveCustomAttributeType() will call ResolveTypeDef() which
+ // will make it back to the AssemblyResolver and back to this function creating an infinite loop.
+ // The TargetFrameworkAttribute will never be generic so we can just skip parsing any generic attributes.
+ if (!CodedToken.CustomAttributeType.Decode(caRow.Type, out MDToken token))
+ continue;
+ if (token.Table == Table.MemberRef &&
+ (!readerModule.TablesStream.TryReadMemberRefRow(token.Rid, out var mrRow) ||
+ readerModule.ResolveMemberRefParent(mrRow.Class, gpContext) is TypeSpec ts &&
+ ts.TypeSig is GenericInstSig))
+ continue;
+
+ var caType = readerModule.ResolveCustomAttributeType(caRow.Type, gpContext);
+ if (!TryGetName(caType, out var ns, out var name))
+ continue;
+ if (ns != nameSystemRuntimeVersioning || name != nameTargetFrameworkAttribute)
+ continue;
+ var ca = CustomAttributeReader.Read(readerModule, caType, caRow.Value, gpContext);
+ if (ca is null || ca.ConstructorArguments.Count != 1)
+ continue;
+ var s = ca.ConstructorArguments[0].Value as UTF8String;
+ if (s is null)
+ continue;
+ if (TryCreateTargetFrameworkInfo(s, out var tmpFramework, out var tmpVersion, out var tmpProfile)) {
+ tfaFramework = tmpFramework;
+ tfaVersion = tmpVersion;
+ tfaProfile = tmpProfile;
+ tfaReturnValue = true;
+ break;
+ }
+ }
+
+ hasInitdTFA = true;
+ }
+ static readonly UTF8String nameSystemRuntimeVersioning = new UTF8String("System.Runtime.Versioning");
+ static readonly UTF8String nameTargetFrameworkAttribute = new UTF8String("TargetFrameworkAttribute");
+
+ static bool TryGetName(ICustomAttributeType caType, out UTF8String ns, out UTF8String name) {
+ ITypeDefOrRef type;
+ if (caType is MemberRef mr)
+ type = mr.DeclaringType;
+ else
+ type = (caType as MethodDef)?.DeclaringType;
+ if (type is TypeRef tr) {
+ ns = tr.Namespace;
+ name = tr.Name;
+ return true;
+ }
+ if (type is TypeDef td) {
+ ns = td.Namespace;
+ name = td.Name;
+ return true;
+ }
+ ns = null;
+ name = null;
+ return false;
+ }
+
+ static bool TryCreateTargetFrameworkInfo(string attrString, out string framework, out Version version, out string profile) {
+ framework = null;
+ version = null;
+ profile = null;
+
+ // See corclr/src/mscorlib/src/System/Runtime/Versioning/BinaryCompatibility.cs
+ var values = attrString.Split(new char[] { ',' });
+ if (values.Length < 2 || values.Length > 3)
+ return false;
+ var frameworkRes = values[0].Trim();
+ if (frameworkRes.Length == 0)
+ return false;
+
+ Version versionRes = null;
+ string profileRes = null;
+ for (int i = 1; i < values.Length; i++) {
+ var kvp = values[i].Split('=');
+ if (kvp.Length != 2)
+ return false;
+
+ var key = kvp[0].Trim();
+ var value = kvp[1].Trim();
+
+ if (key.Equals("Version", StringComparison.OrdinalIgnoreCase)) {
+ if (value.StartsWith("v", StringComparison.OrdinalIgnoreCase))
+ value = value.Substring(1);
+ if (!TryParse(value, out versionRes))
+ return false;
+ versionRes = new Version(versionRes.Major, versionRes.Minor, versionRes.Build == -1 ? 0 : versionRes.Build, 0);
+ }
+ else if (key.Equals("Profile", StringComparison.OrdinalIgnoreCase)) {
+ if (!string.IsNullOrEmpty(value))
+ profileRes = value;
+ }
+ }
+ if (versionRes is null)
+ return false;
+
+ framework = frameworkRes;
+ version = versionRes;
+ profile = profileRes;
+ return true;
+ }
+
+ static int ParseInt32(string s) => int.TryParse(s, out int res) ? res : 0;
+
+ static bool TryParse(string s, out Version version) {
+ Match m;
+
+ m = Regex.Match(s, @"^(\d+)\.(\d+)$");
+ if (m.Groups.Count == 3) {
+ version = new Version(ParseInt32(m.Groups[1].Value), ParseInt32(m.Groups[2].Value));
+ return true;
+ }
+
+ m = Regex.Match(s, @"^(\d+)\.(\d+)\.(\d+)$");
+ if (m.Groups.Count == 4) {
+ version = new Version(ParseInt32(m.Groups[1].Value), ParseInt32(m.Groups[2].Value), ParseInt32(m.Groups[3].Value));
+ return true;
+ }
+
+ m = Regex.Match(s, @"^(\d+)\.(\d+)\.(\d+)\.(\d+)$");
+ if (m.Groups.Count == 5) {
+ version = new Version(ParseInt32(m.Groups[1].Value), ParseInt32(m.Groups[2].Value), ParseInt32(m.Groups[3].Value), ParseInt32(m.Groups[4].Value));
+ return true;
+ }
+
+ version = null;
+ return false;
+ }
+
///
/// Constructor
///
@@ -988,21 +1042,24 @@ protected override void InitializeCustomAttributes() {
/// If is invalid
public AssemblyDefMD(ModuleDefMD readerModule, uint rid) {
#if DEBUG
- if (readerModule == null)
+ if (readerModule is null)
throw new ArgumentNullException("readerModule");
if (readerModule.TablesStream.AssemblyTable.IsInvalidRID(rid))
- throw new BadImageFormatException(string.Format("Assembly rid {0} does not exist", rid));
+ throw new BadImageFormatException($"Assembly rid {rid} does not exist");
#endif
- this.origRid = rid;
+ origRid = rid;
this.rid = rid;
this.readerModule = readerModule;
if (rid != 1)
- this.modules = new LazyList(this);
- uint publicKey, name;
- uint culture = readerModule.TablesStream.ReadAssemblyRow(origRid, out this.hashAlgorithm, out this.version, out this.attributes, out publicKey, out name);
- this.name = readerModule.StringsStream.ReadNoNull(name);
- this.culture = readerModule.StringsStream.ReadNoNull(culture);
- this.publicKey = new PublicKey(readerModule.BlobStream.Read(publicKey));
+ modules = new LazyList(this);
+ bool b = readerModule.TablesStream.TryReadAssemblyRow(origRid, out var row);
+ Debug.Assert(b);
+ hashAlgorithm = (AssemblyHashAlgorithm)row.HashAlgId;
+ version = new Version(row.MajorVersion, row.MinorVersion, row.BuildNumber, row.RevisionNumber);
+ attributes = (int)row.Flags;
+ name = readerModule.StringsStream.ReadNoNull(row.Name);
+ culture = readerModule.StringsStream.ReadNoNull(row.Locale);
+ publicKey = new PublicKey(readerModule.BlobStream.Read(row.PublicKey));
}
}
}
diff --git a/src/DotNet/AssemblyHash.cs b/src/DotNet/AssemblyHash.cs
index 9f01522c9..22de5f3eb 100644
--- a/src/DotNet/AssemblyHash.cs
+++ b/src/DotNet/AssemblyHash.cs
@@ -1,6 +1,6 @@
// dnlib: See LICENSE.txt for more info
-using System;
+using System;
using System.IO;
using System.Security.Cryptography;
@@ -8,7 +8,7 @@ namespace dnlib.DotNet {
///
/// Hashes some data according to a
///
- struct AssemblyHash : IDisposable {
+ readonly struct AssemblyHash : IDisposable {
readonly HashAlgorithm hasher;
///
@@ -17,42 +17,18 @@ struct AssemblyHash : IDisposable {
/// If is an unsupported hash algorithm, then
/// will be used as the hash algorithm.
/// The algorithm to use
- public AssemblyHash(AssemblyHashAlgorithm hashAlgo) {
- switch (hashAlgo) {
- case AssemblyHashAlgorithm.MD5:
- hasher = MD5.Create();
- break;
-
- case AssemblyHashAlgorithm.None:
- case AssemblyHashAlgorithm.MD2:
- case AssemblyHashAlgorithm.MD4:
- case AssemblyHashAlgorithm.SHA1:
- case AssemblyHashAlgorithm.MAC:
- case AssemblyHashAlgorithm.SSL3_SHAMD5:
- case AssemblyHashAlgorithm.HMAC:
- case AssemblyHashAlgorithm.TLS1PRF:
- case AssemblyHashAlgorithm.HASH_REPLACE_OWF:
- default:
- hasher = SHA1.Create();
- break;
-
- case AssemblyHashAlgorithm.SHA_256:
- hasher = SHA256.Create();
- break;
-
- case AssemblyHashAlgorithm.SHA_384:
- hasher = SHA384.Create();
- break;
-
- case AssemblyHashAlgorithm.SHA_512:
- hasher = SHA512.Create();
- break;
- }
- }
+ public AssemblyHash(AssemblyHashAlgorithm hashAlgo) =>
+ hasher = hashAlgo switch {
+ AssemblyHashAlgorithm.MD5 => MD5.Create(),
+ AssemblyHashAlgorithm.SHA_256 => SHA256.Create(),
+ AssemblyHashAlgorithm.SHA_384 => SHA384.Create(),
+ AssemblyHashAlgorithm.SHA_512 => SHA512.Create(),
+ _ => SHA1.Create(),
+ };
///
public void Dispose() {
- if (hasher != null)
+ if (hasher is not null)
((IDisposable)hasher).Dispose();
}
@@ -65,7 +41,7 @@ public void Dispose() {
/// The algorithm to use
/// Hashed data or null if was null
public static byte[] Hash(byte[] data, AssemblyHashAlgorithm hashAlgo) {
- if (data == null)
+ if (data is null)
return null;
using (var asmHash = new AssemblyHash(hashAlgo)) {
@@ -78,9 +54,7 @@ public static byte[] Hash(byte[] data, AssemblyHashAlgorithm hashAlgo) {
/// Hash data
///
/// Data
- public void Hash(byte[] data) {
- Hash(data, 0, data.Length);
- }
+ public void Hash(byte[] data) => Hash(data, 0, data.Length);
///
/// Hash data
@@ -113,7 +87,7 @@ public void Hash(Stream stream, uint length, byte[] buffer) {
/// Computes the hash
///
public byte[] ComputeHash() {
- hasher.TransformFinalBlock(new byte[0], 0, 0);
+ hasher.TransformFinalBlock(Array2.Empty(), 0, 0);
return hasher.Hash;
}
@@ -125,10 +99,10 @@ public byte[] ComputeHash() {
/// The data
/// A new instance
public static PublicKeyToken CreatePublicKeyToken(byte[] publicKeyData) {
- if (publicKeyData == null)
+ if (publicKeyData is null)
return new PublicKeyToken();
var hash = Hash(publicKeyData, AssemblyHashAlgorithm.SHA1);
- byte[] pkt = new byte[8];
+ var pkt = new byte[8];
for (int i = 0; i < pkt.Length && i < hash.Length; i++)
pkt[i] = hash[hash.Length - i - 1];
return new PublicKeyToken(pkt);
diff --git a/src/DotNet/AssemblyHashAlgorithm.cs b/src/DotNet/AssemblyHashAlgorithm.cs
index b1b02853c..8c5913cc5 100644
--- a/src/DotNet/AssemblyHashAlgorithm.cs
+++ b/src/DotNet/AssemblyHashAlgorithm.cs
@@ -1,6 +1,6 @@
// dnlib: See LICENSE.txt for more info
-namespace dnlib.DotNet {
+namespace dnlib.DotNet {
///
/// Any ALG_CLASS_HASH type in WinCrypt.h can be used by Microsoft's CLI implementation
///
@@ -34,22 +34,21 @@ public enum AssemblyHashAlgorithm : uint {
}
public static partial class Extensions {
- internal static string GetName(this AssemblyHashAlgorithm hashAlg) {
- switch (hashAlg) {
- case AssemblyHashAlgorithm.MD2: return null;
- case AssemblyHashAlgorithm.MD4: return null;
- case AssemblyHashAlgorithm.MD5: return "MD5";
- case AssemblyHashAlgorithm.SHA1: return "SHA1";
- case AssemblyHashAlgorithm.MAC: return null;
- case AssemblyHashAlgorithm.SSL3_SHAMD5: return null;
- case AssemblyHashAlgorithm.HMAC: return null;
- case AssemblyHashAlgorithm.TLS1PRF: return null;
- case AssemblyHashAlgorithm.HASH_REPLACE_OWF: return null;
- case AssemblyHashAlgorithm.SHA_256: return "SHA256";
- case AssemblyHashAlgorithm.SHA_384: return "SHA384";
- case AssemblyHashAlgorithm.SHA_512: return "SHA512";
- default: return null;
- }
- }
+ internal static string GetName(this AssemblyHashAlgorithm hashAlg) =>
+ hashAlg switch {
+ AssemblyHashAlgorithm.MD2 => null,
+ AssemblyHashAlgorithm.MD4 => null,
+ AssemblyHashAlgorithm.MD5 => "MD5",
+ AssemblyHashAlgorithm.SHA1 => "SHA1",
+ AssemblyHashAlgorithm.MAC => null,
+ AssemblyHashAlgorithm.SSL3_SHAMD5 => null,
+ AssemblyHashAlgorithm.HMAC => null,
+ AssemblyHashAlgorithm.TLS1PRF => null,
+ AssemblyHashAlgorithm.HASH_REPLACE_OWF => null,
+ AssemblyHashAlgorithm.SHA_256 => "SHA256",
+ AssemblyHashAlgorithm.SHA_384 => "SHA384",
+ AssemblyHashAlgorithm.SHA_512 => "SHA512",
+ _ => null,
+ };
}
}
diff --git a/src/DotNet/AssemblyNameComparer.cs b/src/DotNet/AssemblyNameComparer.cs
index ed6f6535f..4c4a07826 100644
--- a/src/DotNet/AssemblyNameComparer.cs
+++ b/src/DotNet/AssemblyNameComparer.cs
@@ -1,6 +1,6 @@
// dnlib: See LICENSE.txt for more info
-using System;
+using System;
using System.Collections.Generic;
namespace dnlib.DotNet {
@@ -43,66 +43,54 @@ public enum AssemblyNameComparerFlags {
///
/// Compares two assembly names
///
- public struct AssemblyNameComparer : IEqualityComparer {
+ public readonly struct AssemblyNameComparer : IEqualityComparer {
///
/// Compares the name, version, public key token, culture and content type
///
- public static AssemblyNameComparer CompareAll = new AssemblyNameComparer(AssemblyNameComparerFlags.All);
+ public static readonly AssemblyNameComparer CompareAll = new AssemblyNameComparer(AssemblyNameComparerFlags.All);
///
/// Compares only the name and the public key token
///
- public static AssemblyNameComparer NameAndPublicKeyTokenOnly = new AssemblyNameComparer(AssemblyNameComparerFlags.Name | AssemblyNameComparerFlags.PublicKeyToken);
+ public static readonly AssemblyNameComparer NameAndPublicKeyTokenOnly = new AssemblyNameComparer(AssemblyNameComparerFlags.Name | AssemblyNameComparerFlags.PublicKeyToken);
///
/// Compares only the name
///
- public static AssemblyNameComparer NameOnly = new AssemblyNameComparer(AssemblyNameComparerFlags.Name);
+ public static readonly AssemblyNameComparer NameOnly = new AssemblyNameComparer(AssemblyNameComparerFlags.Name);
readonly AssemblyNameComparerFlags flags;
///
/// Gets the bit
///
- public bool CompareName {
- get { return (flags & AssemblyNameComparerFlags.Name) != 0; }
- }
+ public bool CompareName => (flags & AssemblyNameComparerFlags.Name) != 0;
///
/// Gets the bit
///
- public bool CompareVersion {
- get { return (flags & AssemblyNameComparerFlags.Version) != 0; }
- }
+ public bool CompareVersion => (flags & AssemblyNameComparerFlags.Version) != 0;
///
/// Gets the bit
///
- public bool ComparePublicKeyToken {
- get { return (flags & AssemblyNameComparerFlags.PublicKeyToken) != 0; }
- }
+ public bool ComparePublicKeyToken => (flags & AssemblyNameComparerFlags.PublicKeyToken) != 0;
///
/// Gets the bit
///
- public bool CompareCulture {
- get { return (flags & AssemblyNameComparerFlags.Culture) != 0; }
- }
+ public bool CompareCulture => (flags & AssemblyNameComparerFlags.Culture) != 0;
///
/// Gets the bit
///
- public bool CompareContentType {
- get { return (flags & AssemblyNameComparerFlags.ContentType) != 0; }
- }
+ public bool CompareContentType => (flags & AssemblyNameComparerFlags.ContentType) != 0;
///
/// Constructor
///
/// Comparison flags
- public AssemblyNameComparer(AssemblyNameComparerFlags flags) {
- this.flags = flags;
- }
+ public AssemblyNameComparer(AssemblyNameComparerFlags flags) => this.flags = flags;
///
/// Compares two assembly names
@@ -113,9 +101,9 @@ public AssemblyNameComparer(AssemblyNameComparerFlags flags) {
public int CompareTo(IAssembly a, IAssembly b) {
if (a == b)
return 0;
- if (a == null)
+ if (a is null)
return -1;
- if (b == null)
+ if (b is null)
return 1;
int v;
@@ -140,9 +128,7 @@ public int CompareTo(IAssembly a, IAssembly b) {
/// First
/// Second
/// true if equal, false otherwise
- public bool Equals(IAssembly a, IAssembly b) {
- return CompareTo(a, b) == 0;
- }
+ public bool Equals(IAssembly a, IAssembly b) => CompareTo(a, b) == 0;
///
/// Figures out which of two assembly names is closer to another assembly name
@@ -155,9 +141,9 @@ public bool Equals(IAssembly a, IAssembly b) {
public int CompareClosest(IAssembly requested, IAssembly a, IAssembly b) {
if (a == b)
return 0;
- if (a == null)
+ if (a is null)
return !CompareName ? 1 : UTF8String.CaseInsensitiveEquals(requested.Name, b.Name) ? 1 : 0;
- if (b == null)
+ if (b is null)
return !CompareName ? 0 : UTF8String.CaseInsensitiveEquals(requested.Name, a.Name) ? 0 : 1;
// Compare the most important parts first:
@@ -251,7 +237,7 @@ public int CompareClosest(IAssembly requested, IAssembly a, IAssembly b) {
/// Assembly name
/// The hash code
public int GetHashCode(IAssembly a) {
- if (a == null)
+ if (a is null)
return 0;
int hash = 0;
diff --git a/src/DotNet/AssemblyNameInfo.cs b/src/DotNet/AssemblyNameInfo.cs
index 1d1512ec5..9e76d400f 100644
--- a/src/DotNet/AssemblyNameInfo.cs
+++ b/src/DotNet/AssemblyNameInfo.cs
@@ -19,86 +19,59 @@ public sealed class AssemblyNameInfo : IAssembly {
/// Gets/sets the
///
public AssemblyHashAlgorithm HashAlgId {
- get { return hashAlgId; }
- set { hashAlgId = value; }
+ get => hashAlgId;
+ set => hashAlgId = value;
}
///
/// Gets/sets the or null if none specified
///
public Version Version {
- get { return version; }
- set { version = value; }
- }
-
- ///
- /// Gets/sets the
- ///
- [Obsolete("Use Attributes property instead", false)]
- public AssemblyAttributes Flags {
- get { return flags; }
- set { flags = value; }
+ get => version;
+ set => version = value;
}
///
/// Gets/sets the
///
public AssemblyAttributes Attributes {
- get { return flags; }
- set { flags = value; }
+ get => flags;
+ set => flags = value;
}
///
/// Gets/sets the public key or token
///
public PublicKeyBase PublicKeyOrToken {
- get { return publicKeyOrToken; }
- set { publicKeyOrToken = value; }
+ get => publicKeyOrToken;
+ set => publicKeyOrToken = value;
}
///
/// Gets/sets the name
///
public UTF8String Name {
- get { return name; }
- set { name = value; }
- }
-
- ///
- /// Gets/sets the culture or null if none specified
- ///
- [Obsolete("Use Culture property instead", false)]
- public UTF8String Locale {
- get { return Culture; }
- set { Culture = value; }
+ get => name;
+ set => name = value;
}
///
/// Gets/sets the culture or null if none specified
///
public UTF8String Culture {
- get { return culture; }
- set { culture = value; }
+ get => culture;
+ set => culture = value;
}
///
/// Gets the full name of the assembly
///
- public string FullName {
- get { return FullNameToken; }
- }
+ public string FullName => FullNameToken;
///
/// Gets the full name of the assembly but use a public key token
///
- public string FullNameToken {
- get {
- var pk = publicKeyOrToken;
- if (pk is PublicKey)
- pk = (pk as PublicKey).Token;
- return Utils.GetAssemblyNameString(name, version, culture, pk, flags);
- }
- }
+ public string FullNameToken => FullNameFactory.AssemblyFullName(this, true);
///
/// Modify property: =
@@ -106,9 +79,7 @@ public string FullNameToken {
///
/// Value to AND
/// Value to OR
- void ModifyAttributes(AssemblyAttributes andMask, AssemblyAttributes orMask) {
- Attributes = (Attributes & andMask) | orMask;
- }
+ void ModifyAttributes(AssemblyAttributes andMask, AssemblyAttributes orMask) => Attributes = (Attributes & andMask) | orMask;
///
/// Set or clear flags in
@@ -127,128 +98,110 @@ void ModifyAttributes(bool set, AssemblyAttributes flags) {
/// Gets/sets the bit
///
public bool HasPublicKey {
- get { return (Attributes & AssemblyAttributes.PublicKey) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.PublicKey); }
+ get => (Attributes & AssemblyAttributes.PublicKey) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.PublicKey);
}
///
/// Gets/sets the processor architecture
///
public AssemblyAttributes ProcessorArchitecture {
- get { return Attributes & AssemblyAttributes.PA_Mask; }
- set { ModifyAttributes(~AssemblyAttributes.PA_Mask, value & AssemblyAttributes.PA_Mask); }
+ get => Attributes & AssemblyAttributes.PA_Mask;
+ set => ModifyAttributes(~AssemblyAttributes.PA_Mask, value & AssemblyAttributes.PA_Mask);
}
///
/// Gets/sets the processor architecture
///
public AssemblyAttributes ProcessorArchitectureFull {
- get { return Attributes & AssemblyAttributes.PA_FullMask; }
- set { ModifyAttributes(~AssemblyAttributes.PA_FullMask, value & AssemblyAttributes.PA_FullMask); }
+ get => Attributes & AssemblyAttributes.PA_FullMask;
+ set => ModifyAttributes(~AssemblyAttributes.PA_FullMask, value & AssemblyAttributes.PA_FullMask);
}
///
/// true if unspecified processor architecture
///
- public bool IsProcessorArchitectureNone {
- get { return (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_None; }
- }
+ public bool IsProcessorArchitectureNone => (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_None;
///
/// true if neutral (PE32) architecture
///
- public bool IsProcessorArchitectureMSIL {
- get { return (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_MSIL; }
- }
+ public bool IsProcessorArchitectureMSIL => (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_MSIL;
///
/// true if x86 (PE32) architecture
///
- public bool IsProcessorArchitectureX86 {
- get { return (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_x86; }
- }
+ public bool IsProcessorArchitectureX86 => (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_x86;
///
/// true if IA-64 (PE32+) architecture
///
- public bool IsProcessorArchitectureIA64 {
- get { return (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_IA64; }
- }
+ public bool IsProcessorArchitectureIA64 => (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_IA64;
///
/// true if x64 (PE32+) architecture
///
- public bool IsProcessorArchitectureX64 {
- get { return (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_AMD64; }
- }
+ public bool IsProcessorArchitectureX64 => (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_AMD64;
///
/// true if ARM (PE32) architecture
///
- public bool IsProcessorArchitectureARM {
- get { return (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_ARM; }
- }
+ public bool IsProcessorArchitectureARM => (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_ARM;
///
/// true if eg. reference assembly (not runnable)
///
- public bool IsProcessorArchitectureNoPlatform {
- get { return (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_NoPlatform; }
- }
+ public bool IsProcessorArchitectureNoPlatform => (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_NoPlatform;
///
/// Gets/sets the bit
///
public bool IsProcessorArchitectureSpecified {
- get { return (Attributes & AssemblyAttributes.PA_Specified) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.PA_Specified); }
+ get => (Attributes & AssemblyAttributes.PA_Specified) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.PA_Specified);
}
///
/// Gets/sets the bit
///
public bool EnableJITcompileTracking {
- get { return (Attributes & AssemblyAttributes.EnableJITcompileTracking) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.EnableJITcompileTracking); }
+ get => (Attributes & AssemblyAttributes.EnableJITcompileTracking) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.EnableJITcompileTracking);
}
///
/// Gets/sets the bit
///
public bool DisableJITcompileOptimizer {
- get { return (Attributes & AssemblyAttributes.DisableJITcompileOptimizer) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.DisableJITcompileOptimizer); }
+ get => (Attributes & AssemblyAttributes.DisableJITcompileOptimizer) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.DisableJITcompileOptimizer);
}
///
/// Gets/sets the bit
///
public bool IsRetargetable {
- get { return (Attributes & AssemblyAttributes.Retargetable) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.Retargetable); }
+ get => (Attributes & AssemblyAttributes.Retargetable) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.Retargetable);
}
///
/// Gets/sets the content type
///
public AssemblyAttributes ContentType {
- get { return Attributes & AssemblyAttributes.ContentType_Mask; }
- set { ModifyAttributes(~AssemblyAttributes.ContentType_Mask, value & AssemblyAttributes.ContentType_Mask); }
+ get => Attributes & AssemblyAttributes.ContentType_Mask;
+ set => ModifyAttributes(~AssemblyAttributes.ContentType_Mask, value & AssemblyAttributes.ContentType_Mask);
}
///
/// true if content type is Default
///
- public bool IsContentTypeDefault {
- get { return (Attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_Default; }
- }
+ public bool IsContentTypeDefault => (Attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_Default;
///
/// true if content type is WindowsRuntime
///
- public bool IsContentTypeWindowsRuntime {
- get { return (Attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_WindowsRuntime; }
- }
+ public bool IsContentTypeWindowsRuntime => (Attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_WindowsRuntime;
///
/// Default constructor
@@ -269,15 +222,15 @@ public AssemblyNameInfo(string asmFullName)
///
/// The assembly
public AssemblyNameInfo(IAssembly asm) {
- if (asm == null)
+ if (asm is null)
return;
var asmDef = asm as AssemblyDef;
- this.hashAlgId = asmDef == null ? 0 : asmDef.HashAlgorithm;
- this.version = asm.Version ?? new Version(0, 0, 0, 0);
- this.flags = asm.Attributes;
- this.publicKeyOrToken = asm.PublicKeyOrToken;
- this.name = UTF8String.IsNullOrEmpty(asm.Name) ? UTF8String.Empty : asm.Name;
- this.culture = UTF8String.IsNullOrEmpty(asm.Culture) ? UTF8String.Empty : asm.Culture;
+ hashAlgId = asmDef is null ? 0 : asmDef.HashAlgorithm;
+ version = asm.Version ?? new Version(0, 0, 0, 0);
+ flags = asm.Attributes;
+ publicKeyOrToken = asm.PublicKeyOrToken;
+ name = UTF8String.IsNullOrEmpty(asm.Name) ? UTF8String.Empty : asm.Name;
+ culture = UTF8String.IsNullOrEmpty(asm.Culture) ? UTF8String.Empty : asm.Culture;
}
///
@@ -285,20 +238,18 @@ public AssemblyNameInfo(IAssembly asm) {
///
/// Assembly name info
public AssemblyNameInfo(AssemblyName asmName) {
- if (asmName == null)
+ if (asmName is null)
return;
- this.hashAlgId = (AssemblyHashAlgorithm)asmName.HashAlgorithm;
- this.version = asmName.Version ?? new Version(0, 0, 0, 0);
- this.flags = (AssemblyAttributes)asmName.Flags;
- this.publicKeyOrToken = (PublicKeyBase)PublicKeyBase.CreatePublicKey(asmName.GetPublicKey()) ??
+ hashAlgId = (AssemblyHashAlgorithm)asmName.HashAlgorithm;
+ version = asmName.Version ?? new Version(0, 0, 0, 0);
+ flags = (AssemblyAttributes)asmName.Flags;
+ publicKeyOrToken = (PublicKeyBase)PublicKeyBase.CreatePublicKey(asmName.GetPublicKey()) ??
PublicKeyBase.CreatePublicKeyToken(asmName.GetPublicKeyToken());
- this.name = asmName.Name ?? string.Empty;
- this.culture = asmName.CultureInfo != null && asmName.CultureInfo.Name != null ? asmName.CultureInfo.Name : string.Empty;
+ name = asmName.Name ?? string.Empty;
+ culture = asmName.CultureInfo is not null && asmName.CultureInfo.Name is not null ? asmName.CultureInfo.Name : string.Empty;
}
///
- public override string ToString() {
- return FullName;
- }
+ public override string ToString() => FullName;
}
}
diff --git a/src/DotNet/AssemblyRef.cs b/src/DotNet/AssemblyRef.cs
index d92379f1f..f025cfffb 100644
--- a/src/DotNet/AssemblyRef.cs
+++ b/src/DotNet/AssemblyRef.cs
@@ -1,15 +1,18 @@
// dnlib: See LICENSE.txt for more info
using System;
+using System.Collections.Generic;
+using System.Diagnostics;
using System.Reflection;
using System.Threading;
using dnlib.DotNet.MD;
+using dnlib.DotNet.Pdb;
namespace dnlib.DotNet {
///
/// A high-level representation of a row in the AssemblyRef table
///
- public abstract class AssemblyRef : IHasCustomAttribute, IImplementation, IResolutionScope, IAssembly, IScope {
+ public abstract class AssemblyRef : IHasCustomAttribute, IImplementation, IResolutionScope, IHasCustomDebugInformation, IAssembly, IScope {
///
/// An assembly ref that can be used to indicate that it references the current assembly
/// when the current assembly is not known (eg. a type string without any assembly info
@@ -23,40 +26,28 @@ public abstract class AssemblyRef : IHasCustomAttribute, IImplementation, IResol
protected uint rid;
///
- public MDToken MDToken {
- get { return new MDToken(Table.AssemblyRef, rid); }
- }
+ public MDToken MDToken => new MDToken(Table.AssemblyRef, rid);
///
public uint Rid {
- get { return rid; }
- set { rid = value; }
+ get => rid;
+ set => rid = value;
}
///
- public int HasCustomAttributeTag {
- get { return 15; }
- }
+ public int HasCustomAttributeTag => 15;
///
- public int ImplementationTag {
- get { return 1; }
- }
+ public int ImplementationTag => 1;
///
- public int ResolutionScopeTag {
- get { return 2; }
- }
+ public int ResolutionScopeTag => 2;
///
- public ScopeType ScopeType {
- get { return ScopeType.AssemblyRef; }
- }
+ public ScopeType ScopeType => ScopeType.AssemblyRef;
///
- public string ScopeName {
- get { return FullName; }
- }
+ public string ScopeName => FullName;
///
/// From columns AssemblyRef.MajorVersion, AssemblyRef.MinorVersion,
@@ -64,12 +55,8 @@ public string ScopeName {
///
/// If is null
public Version Version {
- get { return version; }
- set {
- if (value == null)
- throw new ArgumentNullException("value");
- version = value;
- }
+ get => version;
+ set => version = value ?? throw new ArgumentNullException(nameof(value));
}
///
protected Version version;
@@ -78,8 +65,8 @@ public Version Version {
/// From column AssemblyRef.Flags
///
public AssemblyAttributes Attributes {
- get { return (AssemblyAttributes)attributes; }
- set { attributes = (int)value; }
+ get => (AssemblyAttributes)attributes;
+ set => attributes = (int)value;
}
/// Attributes
protected int attributes;
@@ -89,12 +76,8 @@ public AssemblyAttributes Attributes {
///
/// If is null
public PublicKeyBase PublicKeyOrToken {
- get { return publicKeyOrToken; }
- set {
- if (value == null)
- throw new ArgumentNullException("value");
- publicKeyOrToken = value;
- }
+ get => publicKeyOrToken;
+ set => publicKeyOrToken = value ?? throw new ArgumentNullException(nameof(value));
}
///
protected PublicKeyBase publicKeyOrToken;
@@ -103,8 +86,8 @@ public PublicKeyBase PublicKeyOrToken {
/// From column AssemblyRef.Name
///
public UTF8String Name {
- get { return name; }
- set { name = value; }
+ get => name;
+ set => name = value;
}
/// Name
protected UTF8String name;
@@ -113,8 +96,8 @@ public UTF8String Name {
/// From column AssemblyRef.Locale
///
public UTF8String Culture {
- get { return culture; }
- set { culture = value; }
+ get => culture;
+ set => culture = value;
}
/// Culture
protected UTF8String culture;
@@ -123,8 +106,8 @@ public UTF8String Culture {
/// From column AssemblyRef.HashValue
///
public byte[] Hash {
- get { return hashValue; }
- set { hashValue = value; }
+ get => hashValue;
+ set => hashValue = value;
}
///
protected byte[] hashValue;
@@ -134,7 +117,7 @@ public byte[] Hash {
///
public CustomAttributeCollection CustomAttributes {
get {
- if (customAttributes == null)
+ if (customAttributes is null)
InitializeCustomAttributes();
return customAttributes;
}
@@ -142,33 +125,46 @@ public CustomAttributeCollection CustomAttributes {
///
protected CustomAttributeCollection customAttributes;
/// Initializes
- protected virtual void InitializeCustomAttributes() {
+ protected virtual void InitializeCustomAttributes() =>
Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null);
- }
///
- public bool HasCustomAttributes {
- get { return CustomAttributes.Count > 0; }
- }
+ public bool HasCustomAttributes => CustomAttributes.Count > 0;
+
+ ///
+ public int HasCustomDebugInformationTag => 15;
///
- public string FullName {
- get { return FullNameToken; }
+ public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0;
+
+ ///
+ /// Gets all custom debug infos
+ ///
+ public IList CustomDebugInfos {
+ get {
+ if (customDebugInfos is null)
+ InitializeCustomDebugInfos();
+ return customDebugInfos;
+ }
}
+ ///
+ protected IList customDebugInfos;
+ /// Initializes
+ protected virtual void InitializeCustomDebugInfos() =>
+ Interlocked.CompareExchange(ref customDebugInfos, new List(), null);
+
+ ///
+ public string FullName => FullNameToken;
///
/// Same as , except that it uses the PublicKey if available.
///
- public string RealFullName {
- get { return Utils.GetAssemblyNameString(name, version, culture, publicKeyOrToken, Attributes); }
- }
+ public string RealFullName => FullNameFactory.AssemblyFullName(this, false);
///
/// Gets the full name of the assembly but use a public key token
///
- public string FullNameToken {
- get { return Utils.GetAssemblyNameString(name, version, culture, PublicKeyBase.ToPublicKeyToken(publicKeyOrToken), Attributes); }
- }
+ public string FullNameToken => FullNameFactory.AssemblyFullName(this, true);
///
/// Modify property: =
@@ -176,17 +172,8 @@ public string FullNameToken {
///
/// Value to AND
/// Value to OR
- void ModifyAttributes(AssemblyAttributes andMask, AssemblyAttributes orMask) {
-#if THREAD_SAFE
- int origVal, newVal;
- do {
- origVal = attributes;
- newVal = (origVal & (int)andMask) | (int)orMask;
- } while (Interlocked.CompareExchange(ref attributes, newVal, origVal) != origVal);
-#else
+ void ModifyAttributes(AssemblyAttributes andMask, AssemblyAttributes orMask) =>
attributes = (attributes & (int)andMask) | (int)orMask;
-#endif
- }
///
/// Set or clear flags in
@@ -195,154 +182,123 @@ void ModifyAttributes(AssemblyAttributes andMask, AssemblyAttributes orMask) {
/// be cleared
/// Flags to set or clear
void ModifyAttributes(bool set, AssemblyAttributes flags) {
-#if THREAD_SAFE
- int origVal, newVal;
- do {
- origVal = attributes;
- if (set)
- newVal = origVal | (int)flags;
- else
- newVal = origVal & ~(int)flags;
- } while (Interlocked.CompareExchange(ref attributes, newVal, origVal) != origVal);
-#else
if (set)
attributes |= (int)flags;
else
attributes &= ~(int)flags;
-#endif
}
///
/// Gets/sets the bit
///
public bool HasPublicKey {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PublicKey) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.PublicKey); }
+ get => ((AssemblyAttributes)attributes & AssemblyAttributes.PublicKey) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.PublicKey);
}
///
/// Gets/sets the processor architecture
///
public AssemblyAttributes ProcessorArchitecture {
- get { return (AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask; }
- set { ModifyAttributes(~AssemblyAttributes.PA_Mask, value & AssemblyAttributes.PA_Mask); }
+ get => (AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask;
+ set => ModifyAttributes(~AssemblyAttributes.PA_Mask, value & AssemblyAttributes.PA_Mask);
}
///
/// Gets/sets the processor architecture
///
public AssemblyAttributes ProcessorArchitectureFull {
- get { return (AssemblyAttributes)attributes & AssemblyAttributes.PA_FullMask; }
- set { ModifyAttributes(~AssemblyAttributes.PA_FullMask, value & AssemblyAttributes.PA_FullMask); }
+ get => (AssemblyAttributes)attributes & AssemblyAttributes.PA_FullMask;
+ set => ModifyAttributes(~AssemblyAttributes.PA_FullMask, value & AssemblyAttributes.PA_FullMask);
}
///
/// true if unspecified processor architecture
///
- public bool IsProcessorArchitectureNone {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_None; }
- }
+ public bool IsProcessorArchitectureNone => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_None;
///
/// true if neutral (PE32) architecture
///
- public bool IsProcessorArchitectureMSIL {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_MSIL; }
- }
+ public bool IsProcessorArchitectureMSIL => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_MSIL;
///
/// true if x86 (PE32) architecture
///
- public bool IsProcessorArchitectureX86 {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_x86; }
- }
+ public bool IsProcessorArchitectureX86 => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_x86;
///
/// true if IA-64 (PE32+) architecture
///
- public bool IsProcessorArchitectureIA64 {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_IA64; }
- }
+ public bool IsProcessorArchitectureIA64 => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_IA64;
///
/// true if x64 (PE32+) architecture
///
- public bool IsProcessorArchitectureX64 {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_AMD64; }
- }
+ public bool IsProcessorArchitectureX64 => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_AMD64;
///
/// true if ARM (PE32) architecture
///
- public bool IsProcessorArchitectureARM {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_ARM; }
- }
+ public bool IsProcessorArchitectureARM => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_ARM;
///
/// true if eg. reference assembly (not runnable)
///
- public bool IsProcessorArchitectureNoPlatform {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_NoPlatform; }
- }
+ public bool IsProcessorArchitectureNoPlatform => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_NoPlatform;
///
/// Gets/sets the bit
///
public bool IsProcessorArchitectureSpecified {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Specified) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.PA_Specified); }
+ get => ((AssemblyAttributes)attributes & AssemblyAttributes.PA_Specified) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.PA_Specified);
}
///
/// Gets/sets the bit
///
public bool EnableJITcompileTracking {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.EnableJITcompileTracking) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.EnableJITcompileTracking); }
+ get => ((AssemblyAttributes)attributes & AssemblyAttributes.EnableJITcompileTracking) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.EnableJITcompileTracking);
}
///
/// Gets/sets the bit
///
public bool DisableJITcompileOptimizer {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.DisableJITcompileOptimizer) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.DisableJITcompileOptimizer); }
+ get => ((AssemblyAttributes)attributes & AssemblyAttributes.DisableJITcompileOptimizer) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.DisableJITcompileOptimizer);
}
///
/// Gets/sets the bit
///
public bool IsRetargetable {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.Retargetable) != 0; }
- set { ModifyAttributes(value, AssemblyAttributes.Retargetable); }
+ get => ((AssemblyAttributes)attributes & AssemblyAttributes.Retargetable) != 0;
+ set => ModifyAttributes(value, AssemblyAttributes.Retargetable);
}
///
/// Gets/sets the content type
///
public AssemblyAttributes ContentType {
- get { return (AssemblyAttributes)attributes & AssemblyAttributes.ContentType_Mask; }
- set { ModifyAttributes(~AssemblyAttributes.ContentType_Mask, value & AssemblyAttributes.ContentType_Mask); }
+ get => (AssemblyAttributes)attributes & AssemblyAttributes.ContentType_Mask;
+ set => ModifyAttributes(~AssemblyAttributes.ContentType_Mask, value & AssemblyAttributes.ContentType_Mask);
}
///
/// true if content type is Default
///
- public bool IsContentTypeDefault {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_Default; }
- }
+ public bool IsContentTypeDefault => ((AssemblyAttributes)attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_Default;
///
/// true if content type is WindowsRuntime
///
- public bool IsContentTypeWindowsRuntime {
- get { return ((AssemblyAttributes)attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_WindowsRuntime; }
- }
+ public bool IsContentTypeWindowsRuntime => ((AssemblyAttributes)attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_WindowsRuntime;
///
- public override string ToString() {
- return FullName;
- }
+ public override string ToString() => FullName;
}
///
@@ -352,30 +308,22 @@ public class AssemblyRefUser : AssemblyRef {
///
/// Creates a reference to CLR 1.0's mscorlib
///
- public static AssemblyRefUser CreateMscorlibReferenceCLR10() {
- return new AssemblyRefUser("mscorlib", new Version(1, 0, 3300, 0), new PublicKeyToken("b77a5c561934e089"));
- }
+ public static AssemblyRefUser CreateMscorlibReferenceCLR10() => new AssemblyRefUser("mscorlib", new Version(1, 0, 3300, 0), new PublicKeyToken("b77a5c561934e089"));
///
/// Creates a reference to CLR 1.1's mscorlib
///
- public static AssemblyRefUser CreateMscorlibReferenceCLR11() {
- return new AssemblyRefUser("mscorlib", new Version(1, 0, 5000, 0), new PublicKeyToken("b77a5c561934e089"));
- }
+ public static AssemblyRefUser CreateMscorlibReferenceCLR11() => new AssemblyRefUser("mscorlib", new Version(1, 0, 5000, 0), new PublicKeyToken("b77a5c561934e089"));
///
/// Creates a reference to CLR 2.0's mscorlib
///
- public static AssemblyRefUser CreateMscorlibReferenceCLR20() {
- return new AssemblyRefUser("mscorlib", new Version(2, 0, 0, 0), new PublicKeyToken("b77a5c561934e089"));
- }
+ public static AssemblyRefUser CreateMscorlibReferenceCLR20() => new AssemblyRefUser("mscorlib", new Version(2, 0, 0, 0), new PublicKeyToken("b77a5c561934e089"));
///
/// Creates a reference to CLR 4.0's mscorlib
///
- public static AssemblyRefUser CreateMscorlibReferenceCLR40() {
- return new AssemblyRefUser("mscorlib", new Version(4, 0, 0, 0), new PublicKeyToken("b77a5c561934e089"));
- }
+ public static AssemblyRefUser CreateMscorlibReferenceCLR40() => new AssemblyRefUser("mscorlib", new Version(4, 0, 0, 0), new PublicKeyToken("b77a5c561934e089"));
///
/// Default constructor
@@ -423,17 +371,15 @@ public AssemblyRefUser(UTF8String name, Version version, PublicKeyBase publicKey
/// Locale
/// If any of the args is invalid
public AssemblyRefUser(UTF8String name, Version version, PublicKeyBase publicKey, UTF8String locale) {
- if ((object)name == null)
- throw new ArgumentNullException("name");
- if (version == null)
- throw new ArgumentNullException("version");
- if ((object)locale == null)
- throw new ArgumentNullException("locale");
+ if (name is null)
+ throw new ArgumentNullException(nameof(name));
+ if (locale is null)
+ throw new ArgumentNullException(nameof(locale));
this.name = name;
- this.version = version;
- this.publicKeyOrToken = publicKey;
- this.culture = locale;
- this.attributes = (int)(publicKey is PublicKey ? AssemblyAttributes.PublicKey : AssemblyAttributes.None);
+ this.version = version ?? throw new ArgumentNullException(nameof(version));
+ publicKeyOrToken = publicKey;
+ culture = locale;
+ attributes = (int)(publicKey is PublicKey ? AssemblyAttributes.PublicKey : AssemblyAttributes.None);
}
///
@@ -442,23 +388,21 @@ public AssemblyRefUser(UTF8String name, Version version, PublicKeyBase publicKey
/// Assembly name info
/// If is null
public AssemblyRefUser(AssemblyName asmName)
- : this(new AssemblyNameInfo(asmName)) {
- this.attributes = (int)asmName.Flags;
- }
+ : this(new AssemblyNameInfo(asmName)) => attributes = (int)asmName.Flags;
///
/// Constructor
///
/// Assembly
public AssemblyRefUser(IAssembly assembly) {
- if (assembly == null)
+ if (assembly is null)
throw new ArgumentNullException("asmName");
- this.version = assembly.Version ?? new Version(0, 0, 0, 0);
- this.publicKeyOrToken = assembly.PublicKeyOrToken;
- this.name = UTF8String.IsNullOrEmpty(assembly.Name) ? UTF8String.Empty : assembly.Name;
- this.culture = assembly.Culture;
- this.attributes = (int)((publicKeyOrToken is PublicKey ? AssemblyAttributes.PublicKey : AssemblyAttributes.None) | assembly.ContentType);
+ version = assembly.Version ?? new Version(0, 0, 0, 0);
+ publicKeyOrToken = assembly.PublicKeyOrToken;
+ name = UTF8String.IsNullOrEmpty(assembly.Name) ? UTF8String.Empty : assembly.Name;
+ culture = assembly.Culture;
+ attributes = (int)((publicKeyOrToken is PublicKey ? AssemblyAttributes.PublicKey : AssemblyAttributes.None) | assembly.ContentType);
}
}
@@ -472,17 +416,22 @@ sealed class AssemblyRefMD : AssemblyRef, IMDTokenProviderMD {
readonly uint origRid;
///
- public uint OrigRid {
- get { return origRid; }
- }
+ public uint OrigRid => origRid;
///
protected override void InitializeCustomAttributes() {
- var list = readerModule.MetaData.GetCustomAttributeRidList(Table.AssemblyRef, origRid);
- var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index]));
+ var list = readerModule.Metadata.GetCustomAttributeRidList(Table.AssemblyRef, origRid);
+ var tmp = new CustomAttributeCollection(list.Count, list, (list2, index) => readerModule.ReadCustomAttribute(list[index]));
Interlocked.CompareExchange(ref customAttributes, tmp, null);
}
+ ///
+ protected override void InitializeCustomDebugInfos() {
+ var list = new List();
+ readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(), list);
+ Interlocked.CompareExchange(ref customDebugInfos, list, null);
+ }
+
///
/// Constructor
///
@@ -492,24 +441,26 @@ protected override void InitializeCustomAttributes() {
/// If is invalid
public AssemblyRefMD(ModuleDefMD readerModule, uint rid) {
#if DEBUG
- if (readerModule == null)
+ if (readerModule is null)
throw new ArgumentNullException("readerModule");
if (readerModule.TablesStream.AssemblyRefTable.IsInvalidRID(rid))
- throw new BadImageFormatException(string.Format("AssemblyRef rid {0} does not exist", rid));
+ throw new BadImageFormatException($"AssemblyRef rid {rid} does not exist");
#endif
- this.origRid = rid;
+ origRid = rid;
this.rid = rid;
this.readerModule = readerModule;
- uint publicKeyOrToken, name, culture;
- uint hashValue = readerModule.TablesStream.ReadAssemblyRefRow(origRid, out this.version, out this.attributes, out publicKeyOrToken, out name, out culture);
- var pkData = readerModule.BlobStream.Read(publicKeyOrToken);
- if ((this.attributes & (uint)AssemblyAttributes.PublicKey) != 0)
- this.publicKeyOrToken = new PublicKey(pkData);
+ bool b = readerModule.TablesStream.TryReadAssemblyRefRow(origRid, out var row);
+ Debug.Assert(b);
+ version = new Version(row.MajorVersion, row.MinorVersion, row.BuildNumber, row.RevisionNumber);
+ attributes = (int)row.Flags;
+ var pkData = readerModule.BlobStream.Read(row.PublicKeyOrToken);
+ if ((attributes & (uint)AssemblyAttributes.PublicKey) != 0)
+ publicKeyOrToken = new PublicKey(pkData);
else
- this.publicKeyOrToken = new PublicKeyToken(pkData);
- this.name = readerModule.StringsStream.ReadNoNull(name);
- this.culture = readerModule.StringsStream.ReadNoNull(culture);
- this.hashValue = readerModule.BlobStream.Read(hashValue);
+ publicKeyOrToken = new PublicKeyToken(pkData);
+ name = readerModule.StringsStream.ReadNoNull(row.Name);
+ culture = readerModule.StringsStream.ReadNoNull(row.Locale);
+ hashValue = readerModule.BlobStream.Read(row.HashValue);
}
}
}
diff --git a/src/DotNet/AssemblyResolver.cs b/src/DotNet/AssemblyResolver.cs
index b46c70c78..791399d1c 100644
--- a/src/DotNet/AssemblyResolver.cs
+++ b/src/DotNet/AssemblyResolver.cs
@@ -1,18 +1,12 @@
// dnlib: See LICENSE.txt for more info
-using System;
+using System;
using System.Collections.Generic;
using System.IO;
-using System.Text.RegularExpressions;
+using System.Linq;
using System.Xml;
using dnlib.Threading;
-#if THREAD_SAFE
-using ThreadSafe = dnlib.Threading.Collections;
-#else
-using ThreadSafe = System.Collections.Generic;
-#endif
-
namespace dnlib.DotNet {
///
/// Resolves assemblies
@@ -25,45 +19,47 @@ public class AssemblyResolver : IAssemblyResolver {
static readonly string[] winMDAssemblyExtensions = new string[] { ".winmd" };
static readonly List gacInfos;
- static readonly List extraMonoPaths;
+ static readonly string[] extraMonoPaths;
static readonly string[] monoVerDirs = new string[] {
- "4.5", "4.0",
- "3.5", "3.0", "2.0",
+ // The "-api" dirs are reference assembly dirs.
+ "4.5", @"4.5\Facades", "4.5-api", @"4.5-api\Facades", "4.0", "4.0-api",
+ "3.5", "3.5-api", "3.0", "3.0-api", "2.0", "2.0-api",
"1.1", "1.0",
};
ModuleContext defaultModuleContext;
- readonly Dictionary> moduleSearchPaths = new Dictionary>();
- readonly Dictionary cachedAssemblies = new Dictionary(StringComparer.Ordinal);
- readonly ThreadSafe.IList preSearchPaths = ThreadSafeListCreator.Create();
- readonly ThreadSafe.IList postSearchPaths = ThreadSafeListCreator.Create();
+ readonly Dictionary> moduleSearchPaths = new Dictionary>();
+ readonly Dictionary cachedAssemblies = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ readonly List preSearchPaths = new List();
+ readonly List postSearchPaths = new List();
bool findExactMatch;
bool enableFrameworkRedirect;
- bool enableTypeDefCache;
+ bool enableTypeDefCache = true;
+ bool useGac = true;
#if THREAD_SAFE
readonly Lock theLock = Lock.Create();
#endif
sealed class GacInfo {
- public readonly int version;
- public readonly string path;
- public readonly string prefix;
- public readonly IList subDirs;
+ public readonly int Version;
+ public readonly string Path;
+ public readonly string Prefix;
+ public readonly string[] SubDirs;
- public GacInfo(int version, string prefix, string path, IList subDirs) {
- this.version = version;
- this.prefix = prefix;
- this.path = path;
- this.subDirs = subDirs;
+ public GacInfo(int version, string prefix, string path, string[] subDirs) {
+ Version = version;
+ Prefix = prefix;
+ Path = path;
+ SubDirs = subDirs;
}
}
static AssemblyResolver() {
gacInfos = new List();
- if (Type.GetType("Mono.Runtime") != null) {
+ if (Type.GetType("Mono.Runtime") is not null) {
var dirs = new Dictionary(StringComparer.OrdinalIgnoreCase);
- extraMonoPaths = new List();
+ var extraMonoPathsList = new List();
foreach (var prefix in FindMonoPrefixes()) {
var dir = Path.Combine(Path.Combine(Path.Combine(prefix, "lib"), "mono"), "gac");
if (dirs.ContainsKey(dir))
@@ -78,26 +74,30 @@ static AssemblyResolver() {
dir = Path.GetDirectoryName(dir);
foreach (var verDir in monoVerDirs) {
- var dir2 = Path.Combine(dir, verDir);
+ var dir2 = dir;
+ foreach (var d in verDir.Split(new char[] { '\\' }))
+ dir2 = Path.Combine(dir2, d);
if (Directory.Exists(dir2))
- extraMonoPaths.Add(dir2);
+ extraMonoPathsList.Add(dir2);
}
}
var paths = Environment.GetEnvironmentVariable("MONO_PATH");
- if (paths != null) {
- foreach (var path in paths.Split(Path.PathSeparator)) {
+ if (paths is not null) {
+ foreach (var tmp in paths.Split(Path.PathSeparator)) {
+ var path = tmp.Trim();
if (path != string.Empty && Directory.Exists(path))
- extraMonoPaths.Add(path);
+ extraMonoPathsList.Add(path);
}
}
+ extraMonoPaths = extraMonoPathsList.ToArray();
}
else {
var windir = Environment.GetEnvironmentVariable("WINDIR");
if (!string.IsNullOrEmpty(windir)) {
string path;
- // .NET 1.x and 2.x
+ // .NET Framework 1.x and 2.x
path = Path.Combine(windir, "assembly");
if (Directory.Exists(path)) {
gacInfos.Add(new GacInfo(2, "", path, new string[] {
@@ -105,7 +105,7 @@ static AssemblyResolver() {
}));
}
- // .NET 4.x
+ // .NET Framework 4.x
path = Path.Combine(Path.Combine(windir, "Microsoft.NET"), "assembly");
if (Directory.Exists(path)) {
gacInfos.Add(new GacInfo(4, "v4.0_", path, new string[] {
@@ -128,7 +128,8 @@ static IEnumerable FindMonoPrefixes() {
var prefixes = Environment.GetEnvironmentVariable("MONO_GAC_PREFIX");
if (!string.IsNullOrEmpty(prefixes)) {
- foreach (var prefix in prefixes.Split(Path.PathSeparator)) {
+ foreach (var tmp in prefixes.Split(Path.PathSeparator)) {
+ var prefix = tmp.Trim();
if (prefix != string.Empty)
yield return prefix;
}
@@ -139,8 +140,8 @@ static IEnumerable FindMonoPrefixes() {
/// Gets/sets the default
///
public ModuleContext DefaultModuleContext {
- get { return defaultModuleContext; }
- set { defaultModuleContext = value; }
+ get => defaultModuleContext;
+ set => defaultModuleContext = value;
}
///
@@ -149,75 +150,68 @@ public ModuleContext DefaultModuleContext {
/// assembly that is closest to the requested assembly.
///
public bool FindExactMatch {
- get { return findExactMatch; }
- set { findExactMatch = value; }
+ get => findExactMatch;
+ set => findExactMatch = value;
}
///
/// true if resolved .NET framework assemblies can be redirected to the source
- /// module's framework assembly version. Eg. if a resolved .NET 3.5 assembly can be
- /// redirected to a .NET 4.0 assembly if the source module is a .NET 4.0 assembly. This is
+ /// module's framework assembly version. Eg. if a resolved .NET Framework 3.5 assembly can be
+ /// redirected to a .NET Framework 4.0 assembly if the source module is a .NET Framework 4.0 assembly. This is
/// ignored if is true.
///
public bool EnableFrameworkRedirect {
- get { return enableFrameworkRedirect; }
- set { enableFrameworkRedirect = value; }
+ get => enableFrameworkRedirect;
+ set => enableFrameworkRedirect = value;
}
///
/// If true, all modules in newly resolved assemblies will have their
- /// property set to true.
+ /// property set to true. This is
+ /// enabled by default since these modules shouldn't be modified by the user.
///
public bool EnableTypeDefCache {
- get { return enableTypeDefCache; }
- set { enableTypeDefCache = value; }
+ get => enableTypeDefCache;
+ set => enableTypeDefCache = value;
}
///
- /// Gets paths searched before trying the standard locations
+ /// true to search the Global Assembly Cache. Default value is true.
///
- public ThreadSafe.IList PreSearchPaths {
- get { return preSearchPaths; }
+ public bool UseGAC {
+ get => useGac;
+ set => useGac = value;
}
///
- /// Gets paths searched after trying the standard locations
+ /// Gets paths searched before trying the standard locations
///
- public ThreadSafe.IList PostSearchPaths {
- get { return postSearchPaths; }
- }
+ public IList PreSearchPaths => preSearchPaths;
///
- /// Default constructor
+ /// Gets paths searched after trying the standard locations
///
- public AssemblyResolver()
- : this(null, true) {
- }
+ public IList PostSearchPaths => postSearchPaths;
///
- /// Constructor
+ /// Default constructor
///
- /// Module context for all resolved assemblies
- public AssemblyResolver(ModuleContext defaultModuleContext)
- : this(defaultModuleContext, true) {
+ public AssemblyResolver()
+ : this(null) {
}
///
/// Constructor
///
/// Module context for all resolved assemblies
- /// If true, add other common assembly search
- /// paths, not just the module search paths and the GAC.
- public AssemblyResolver(ModuleContext defaultModuleContext, bool addOtherSearchPaths) {
+ public AssemblyResolver(ModuleContext defaultModuleContext) {
this.defaultModuleContext = defaultModuleContext;
- this.enableFrameworkRedirect = true;
- if (addOtherSearchPaths)
- AddOtherSearchPaths(postSearchPaths);
+ enableFrameworkRedirect = true;
}
///
public AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule) {
- if (assembly == null)
+ if (assembly is null)
return null;
if (EnableFrameworkRedirect && !FindExactMatch)
@@ -226,8 +220,8 @@ public AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule) {
#if THREAD_SAFE
theLock.EnterWriteLock(); try {
#endif
- AssemblyDef resolvedAssembly = Resolve2(assembly, sourceModule);
- if (resolvedAssembly == null) {
+ var resolvedAssembly = Resolve2(assembly, sourceModule);
+ if (resolvedAssembly is null) {
string asmName = UTF8String.ToSystemStringOrEmpty(assembly.Name);
string asmNameTrimmed = asmName.Trim();
if (asmName != asmNameTrimmed) {
@@ -241,7 +235,7 @@ public AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule) {
}
}
- if (resolvedAssembly == null) {
+ if (resolvedAssembly is null) {
// Make sure we don't search for this assembly again. This speeds up callers who
// keep asking for this assembly when trying to resolve many different TypeRefs
cachedAssemblies[GetAssemblyNameKey(assembly)] = null;
@@ -250,15 +244,17 @@ public AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule) {
var key1 = GetAssemblyNameKey(resolvedAssembly);
var key2 = GetAssemblyNameKey(assembly);
- AssemblyDef asm1, asm2;
- cachedAssemblies.TryGetValue(key1, out asm1);
- cachedAssemblies.TryGetValue(key2, out asm2);
+ cachedAssemblies.TryGetValue(key1, out var asm1);
+ cachedAssemblies.TryGetValue(key2, out var asm2);
if (asm1 != resolvedAssembly && asm2 != resolvedAssembly) {
// This assembly was just resolved
if (enableTypeDefCache) {
- foreach (var module in resolvedAssembly.Modules.GetSafeEnumerable()) {
- if (module != null)
+ var modules = resolvedAssembly.Modules;
+ int count = modules.Count;
+ for (int i = 0; i < count; i++) {
+ var module = modules[i];
+ if (module is not null)
module.EnableTypeDefFindCache = true;
}
}
@@ -278,7 +274,7 @@ public AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule) {
// Dupe assembly. Don't insert it.
var dupeModule = resolvedAssembly.ManifestModule;
- if (dupeModule != null)
+ if (dupeModule is not null)
dupeModule.Dispose();
return asm1 ?? asm2;
#if THREAD_SAFE
@@ -286,16 +282,30 @@ public AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule) {
#endif
}
- ///
+ ///
+ /// Add a module's assembly to the assembly cache
+ ///
+ /// The module whose assembly should be cached
+ /// true if 's assembly is cached, false
+ /// if it's not cached because some other assembly with the exact same full name has
+ /// already been cached or if or its assembly is null.
+ public bool AddToCache(ModuleDef module) => module is not null && AddToCache(module.Assembly);
+
+ ///
+ /// Add an assembly to the assembly cache
+ ///
+ /// The assembly
+ /// true if is cached, false if it's not
+ /// cached because some other assembly with the exact same full name has already been
+ /// cached or if is null.
public bool AddToCache(AssemblyDef asm) {
- if (asm == null)
+ if (asm is null)
return false;
var asmKey = GetAssemblyNameKey(asm);
- AssemblyDef cachedAsm;
#if THREAD_SAFE
theLock.EnterWriteLock(); try {
#endif
- if (cachedAssemblies.TryGetValue(asmKey, out cachedAsm) && cachedAsm != null)
+ if (cachedAssemblies.TryGetValue(asmKey, out var cachedAsm) && cachedAsm is not null)
return asm == cachedAsm;
cachedAssemblies[asmKey] = asm;
return true;
@@ -304,21 +314,42 @@ public bool AddToCache(AssemblyDef asm) {
#endif
}
- ///
+ ///
+ /// Removes a module's assembly from the cache
+ ///
+ /// The module
+ /// true if its assembly was removed, false if it wasn't removed
+ /// since it wasn't in the cache, it has no assembly, or was
+ /// null
+ public bool Remove(ModuleDef module) => module is not null && Remove(module.Assembly);
+
+ ///
+ /// Removes the assembly from the cache
+ ///
+ /// The assembly
+ /// true if it was removed, false if it wasn't removed since it
+ /// wasn't in the cache or if was null
public bool Remove(AssemblyDef asm) {
- if (asm == null)
+ if (asm is null)
return false;
var asmKey = GetAssemblyNameKey(asm);
#if THREAD_SAFE
theLock.EnterWriteLock(); try {
#endif
+ if (asm.ManifestModule is { } module)
+ moduleSearchPaths.Remove(module);
return cachedAssemblies.Remove(asmKey);
#if THREAD_SAFE
} finally { theLock.ExitWriteLock(); }
#endif
}
- ///
+ ///
+ /// Clears the cache and calls on each cached module.
+ /// Use to remove any assemblies you added yourself
+ /// using before calling this method if you don't want
+ /// them disposed.
+ ///
public void Clear() {
List asms;
#if THREAD_SAFE
@@ -326,36 +357,51 @@ public void Clear() {
#endif
asms = new List(cachedAssemblies.Values);
cachedAssemblies.Clear();
+ moduleSearchPaths.Clear();
#if THREAD_SAFE
} finally { theLock.ExitWriteLock(); }
#endif
foreach (var asm in asms) {
- if (asm == null)
+ if (asm is null)
continue;
- foreach (var mod in asm.Modules.GetSafeEnumerable())
+ foreach (var mod in asm.Modules)
mod.Dispose();
}
}
+ ///
+ /// Gets the cached assemblies in this resolver.
+ ///
+ /// The cached assemblies.
+ public IEnumerable GetCachedAssemblies() {
+ AssemblyDef[] assemblies;
+#if THREAD_SAFE
+ theLock.EnterReadLock(); try {
+#endif
+ assemblies = cachedAssemblies.Values.ToArray();
+#if THREAD_SAFE
+ } finally { theLock.ExitReadLock(); }
+#endif
+ return assemblies;
+ }
+
static string GetAssemblyNameKey(IAssembly asmName) {
// Make sure the name contains PublicKeyToken= and not PublicKey=
- return asmName.FullNameToken.ToUpperInvariant();
+ return asmName.FullNameToken;
}
AssemblyDef Resolve2(IAssembly assembly, ModuleDef sourceModule) {
- AssemblyDef resolvedAssembly;
-
- if (cachedAssemblies.TryGetValue(GetAssemblyNameKey(assembly), out resolvedAssembly))
+ if (cachedAssemblies.TryGetValue(GetAssemblyNameKey(assembly), out var resolvedAssembly))
return resolvedAssembly;
var moduleContext = defaultModuleContext;
- if (moduleContext == null && sourceModule != null)
+ if (moduleContext is null && sourceModule is not null)
moduleContext = sourceModule.Context;
resolvedAssembly = FindExactAssembly(assembly, PreFindAssemblies(assembly, sourceModule, true), moduleContext) ??
FindExactAssembly(assembly, FindAssemblies(assembly, sourceModule, true), moduleContext) ??
FindExactAssembly(assembly, PostFindAssemblies(assembly, sourceModule, true), moduleContext);
- if (resolvedAssembly != null)
+ if (resolvedAssembly is not null)
return resolvedAssembly;
if (!findExactMatch) {
@@ -377,15 +423,15 @@ AssemblyDef Resolve2(IAssembly assembly, ModuleDef sourceModule) {
/// An instance or null if an exact match
/// couldn't be found.
AssemblyDef FindExactAssembly(IAssembly assembly, IEnumerable paths, ModuleContext moduleContext) {
- if (paths == null)
+ if (paths is null)
return null;
var asmComparer = AssemblyNameComparer.CompareAll;
- foreach (var path in paths.GetSafeEnumerable()) {
+ foreach (var path in paths) {
ModuleDefMD mod = null;
try {
mod = ModuleDefMD.Load(path, moduleContext);
var asm = mod.Assembly;
- if (asm != null && asmComparer.Equals(assembly, asm)) {
+ if (asm is not null && asmComparer.Equals(assembly, asm)) {
mod = null;
return asm;
}
@@ -393,7 +439,7 @@ AssemblyDef FindExactAssembly(IAssembly assembly, IEnumerable paths, Mod
catch {
}
finally {
- if (mod != null)
+ if (mod is not null)
mod.Dispose();
}
}
@@ -408,8 +454,9 @@ AssemblyDef FindExactAssembly(IAssembly assembly, IEnumerable paths, Mod
AssemblyDef FindClosestAssembly(IAssembly assembly) {
AssemblyDef closest = null;
var asmComparer = AssemblyNameComparer.CompareAll;
- foreach (var asm in cachedAssemblies.Values) {
- if (asm == null)
+ foreach (var kv in cachedAssemblies) {
+ var asm = kv.Value;
+ if (asm is null)
continue;
if (asmComparer.CompareClosest(assembly, closest, asm) == 1)
closest = asm;
@@ -418,18 +465,18 @@ AssemblyDef FindClosestAssembly(IAssembly assembly) {
}
AssemblyDef FindClosestAssembly(IAssembly assembly, AssemblyDef closest, IEnumerable paths, ModuleContext moduleContext) {
- if (paths == null)
+ if (paths is null)
return closest;
var asmComparer = AssemblyNameComparer.CompareAll;
- foreach (var path in paths.GetSafeEnumerable()) {
+ foreach (var path in paths) {
ModuleDefMD mod = null;
try {
mod = ModuleDefMD.Load(path, moduleContext);
var asm = mod.Assembly;
- if (asm != null && asmComparer.CompareClosest(assembly, closest, asm) == 1) {
- if (!IsCached(closest) && closest != null) {
+ if (asm is not null && asmComparer.CompareClosest(assembly, closest, asm) == 1) {
+ if (!IsCached(closest) && closest is not null) {
var closeMod = closest.ManifestModule;
- if (closeMod != null)
+ if (closeMod is not null)
closeMod.Dispose();
}
closest = asm;
@@ -439,7 +486,7 @@ AssemblyDef FindClosestAssembly(IAssembly assembly, AssemblyDef closest, IEnumer
catch {
}
finally {
- if (mod != null)
+ if (mod is not null)
mod.Dispose();
}
}
@@ -452,20 +499,26 @@ AssemblyDef FindClosestAssembly(IAssembly assembly, AssemblyDef closest, IEnumer
///
/// Assembly to check
bool IsCached(AssemblyDef asm) {
- if (asm == null)
+ if (asm is null)
return false;
- AssemblyDef cachedAsm;
- return cachedAssemblies.TryGetValue(GetAssemblyNameKey(asm), out cachedAsm) &&
+ return cachedAssemblies.TryGetValue(GetAssemblyNameKey(asm), out var cachedAsm) &&
cachedAsm == asm;
}
IEnumerable FindAssemblies2(IAssembly assembly, IEnumerable paths) {
- if (paths != null) {
+ if (paths is not null) {
var asmSimpleName = UTF8String.ToSystemStringOrEmpty(assembly.Name);
var exts = assembly.IsContentTypeWindowsRuntime ? winMDAssemblyExtensions : assemblyExtensions;
foreach (var ext in exts) {
- foreach (var path in paths.GetSafeEnumerable()) {
- var fullPath = Path.Combine(path, asmSimpleName + ext);
+ foreach (var path in paths) {
+ string fullPath;
+ try {
+ fullPath = Path.Combine(path, asmSimpleName + ext);
+ }
+ catch (ArgumentException) {
+ // Invalid path chars
+ yield break;
+ }
if (File.Exists(fullPath))
yield return fullPath;
}
@@ -506,13 +559,22 @@ protected virtual IEnumerable PostFindAssemblies(IAssembly assembly, Mod
/// null or an enumerable of full paths to try
protected virtual IEnumerable FindAssemblies(IAssembly assembly, ModuleDef sourceModule, bool matchExactly) {
if (assembly.IsContentTypeWindowsRuntime) {
- var path = Path.Combine(Path.Combine(Environment.SystemDirectory, "WinMetadata"), assembly.Name + ".winmd");
+ string path;
+ try {
+ path = Path.Combine(Path.Combine(Environment.SystemDirectory, "WinMetadata"), assembly.Name + ".winmd");
+ }
+ catch (ArgumentException) {
+ // Invalid path chars
+ path = null;
+ }
if (File.Exists(path))
yield return path;
}
else {
- foreach (var path in FindAssembliesGac(assembly, sourceModule, matchExactly))
- yield return path;
+ if (UseGAC) {
+ foreach (var path in FindAssembliesGac(assembly, sourceModule, matchExactly))
+ yield return path;
+ }
}
foreach (var path in FindAssembliesModuleSearchPaths(assembly, sourceModule, matchExactly))
yield return path;
@@ -525,14 +587,14 @@ IEnumerable FindAssembliesGac(IAssembly assembly, ModuleDef sourceModule
}
IEnumerable GetGacInfos(ModuleDef sourceModule) {
- int version = sourceModule == null ? int.MinValue : sourceModule.IsClr40 ? 4 : 2;
- // Try the correct GAC first (eg. GAC4 if it's a .NET 4 assembly)
+ int version = sourceModule is null ? int.MinValue : sourceModule.IsClr40 ? 4 : 2;
+ // Try the correct GAC first (eg. GAC4 if it's a .NET Framework 4 assembly)
foreach (var gacInfo in gacInfos) {
- if (gacInfo.version == version)
+ if (gacInfo.Version == version)
yield return gacInfo;
}
foreach (var gacInfo in gacInfos) {
- if (gacInfo.version != version)
+ if (gacInfo.Version != version)
yield return gacInfo;
}
}
@@ -542,16 +604,23 @@ IEnumerable FindAssembliesGacExactly(IAssembly assembly, ModuleDef sourc
foreach (var path in FindAssembliesGacExactly(gacInfo, assembly, sourceModule))
yield return path;
}
- if (extraMonoPaths != null) {
+ if (extraMonoPaths is not null) {
foreach (var path in GetExtraMonoPaths(assembly, sourceModule))
yield return path;
}
}
static IEnumerable GetExtraMonoPaths(IAssembly assembly, ModuleDef sourceModule) {
- if (extraMonoPaths != null) {
+ if (extraMonoPaths is not null) {
foreach (var dir in extraMonoPaths) {
- var file = Path.Combine(dir, assembly.Name + ".dll");
+ string file;
+ try {
+ file = Path.Combine(dir, assembly.Name + ".dll");
+ }
+ catch (ArgumentException) {
+ // Invalid path chars
+ break;
+ }
if (File.Exists(file))
yield return file;
}
@@ -560,14 +629,23 @@ static IEnumerable GetExtraMonoPaths(IAssembly assembly, ModuleDef sourc
IEnumerable FindAssembliesGacExactly(GacInfo gacInfo, IAssembly assembly, ModuleDef sourceModule) {
var pkt = PublicKeyBase.ToPublicKeyToken(assembly.PublicKeyOrToken);
- if (gacInfo != null && pkt != null) {
+ if (gacInfo is not null && pkt is not null) {
string pktString = pkt.ToString();
string verString = Utils.CreateVersionWithNoUndefinedValues(assembly.Version).ToString();
+ var cultureString = UTF8String.ToSystemStringOrEmpty(assembly.Culture);
+ if (cultureString.Equals("neutral", StringComparison.OrdinalIgnoreCase))
+ cultureString = string.Empty;
var asmSimpleName = UTF8String.ToSystemStringOrEmpty(assembly.Name);
- foreach (var subDir in gacInfo.subDirs) {
- var baseDir = Path.Combine(gacInfo.path, subDir);
- baseDir = Path.Combine(baseDir, asmSimpleName);
- baseDir = Path.Combine(baseDir, string.Format("{0}{1}__{2}", gacInfo.prefix, verString, pktString));
+ foreach (var subDir in gacInfo.SubDirs) {
+ var baseDir = Path.Combine(gacInfo.Path, subDir);
+ try {
+ baseDir = Path.Combine(baseDir, asmSimpleName);
+ }
+ catch (ArgumentException) {
+ // Invalid path chars
+ break;
+ }
+ baseDir = Path.Combine(baseDir, $"{gacInfo.Prefix}{verString}_{cultureString}_{pktString}");
var pathName = Path.Combine(baseDir, asmSimpleName + ".dll");
if (File.Exists(pathName))
yield return pathName;
@@ -580,18 +658,24 @@ IEnumerable FindAssembliesGacAny(IAssembly assembly, ModuleDef sourceMod
foreach (var path in FindAssembliesGacAny(gacInfo, assembly, sourceModule))
yield return path;
}
- if (extraMonoPaths != null) {
+ if (extraMonoPaths is not null) {
foreach (var path in GetExtraMonoPaths(assembly, sourceModule))
yield return path;
}
}
IEnumerable FindAssembliesGacAny(GacInfo gacInfo, IAssembly assembly, ModuleDef sourceModule) {
- if (gacInfo != null) {
+ if (gacInfo is not null) {
var asmSimpleName = UTF8String.ToSystemStringOrEmpty(assembly.Name);
- foreach (var subDir in gacInfo.subDirs) {
- var baseDir = Path.Combine(gacInfo.path, subDir);
- baseDir = Path.Combine(baseDir, asmSimpleName);
+ foreach (var subDir in gacInfo.SubDirs) {
+ var baseDir = Path.Combine(gacInfo.Path, subDir);
+ try {
+ baseDir = Path.Combine(baseDir, asmSimpleName);
+ }
+ catch (ArgumentException) {
+ // Invalid path chars
+ break;
+ }
foreach (var dir in GetDirs(baseDir)) {
var pathName = Path.Combine(dir, asmSimpleName + ".dll");
if (File.Exists(pathName))
@@ -602,6 +686,8 @@ IEnumerable FindAssembliesGacAny(GacInfo gacInfo, IAssembly assembly, Mo
}
IEnumerable GetDirs(string baseDir) {
+ if (!Directory.Exists(baseDir))
+ return Array2.Empty();
var dirs = new List();
try {
foreach (var di in new DirectoryInfo(baseDir).GetDirectories())
@@ -617,13 +703,19 @@ IEnumerable FindAssembliesModuleSearchPaths(IAssembly assembly, ModuleDe
var searchPaths = GetSearchPaths(sourceModule);
var exts = assembly.IsContentTypeWindowsRuntime ? winMDAssemblyExtensions : assemblyExtensions;
foreach (var ext in exts) {
- foreach (var path in searchPaths.GetSafeEnumerable()) {
+ foreach (var path in searchPaths) {
for (int i = 0; i < 2; i++) {
string path2;
- if (i == 0)
- path2 = Path.Combine(path, asmSimpleName + ext);
- else
- path2 = Path.Combine(Path.Combine(path, asmSimpleName), asmSimpleName + ext);
+ try {
+ if (i == 0)
+ path2 = Path.Combine(path, asmSimpleName + ext);
+ else
+ path2 = Path.Combine(Path.Combine(path, asmSimpleName), asmSimpleName + ext);
+ }
+ catch (ArgumentException) {
+ // Invalid path chars
+ yield break;
+ }
if (File.Exists(path2))
yield return path2;
}
@@ -637,11 +729,10 @@ IEnumerable FindAssembliesModuleSearchPaths(IAssembly assembly, ModuleDe
/// The module or null if unknown
/// A list of all search paths to use for this module
IEnumerable GetSearchPaths(ModuleDef module) {
- ModuleDef keyModule = module;
- if (keyModule == null)
+ var keyModule = module;
+ if (keyModule is null)
keyModule = nullModule;
- IList searchPaths;
- if (moduleSearchPaths.TryGetValue(keyModule, out searchPaths))
+ if (moduleSearchPaths.TryGetValue(keyModule, out var searchPaths))
return searchPaths;
moduleSearchPaths[keyModule] = searchPaths = new List(GetModuleSearchPaths(module));
return searchPaths;
@@ -654,9 +745,7 @@ IEnumerable GetSearchPaths(ModuleDef module) {
///
/// The module or null if unknown
/// A list of search paths
- protected virtual IEnumerable GetModuleSearchPaths(ModuleDef module) {
- return GetModulePrivateSearchPaths(module);
- }
+ protected virtual IEnumerable GetModuleSearchPaths(ModuleDef module) => GetModulePrivateSearchPaths(module);
///
/// Gets all private assembly search paths as found in the module's .config file.
@@ -664,30 +753,33 @@ protected virtual IEnumerable GetModuleSearchPaths(ModuleDef module) {
/// The module or null if unknown
/// A list of search paths
protected IEnumerable GetModulePrivateSearchPaths(ModuleDef module) {
- if (module == null)
- return new string[0];
+ if (module is null)
+ return Array2.Empty();
var asm = module.Assembly;
- if (asm == null)
- return new string[0];
+ if (asm is null)
+ return Array2.Empty();
module = asm.ManifestModule;
- if (module == null)
- return new string[0]; // Should never happen
+ if (module is null)
+ return Array2.Empty(); // Should never happen
string baseDir = null;
try {
var imageName = module.Location;
if (imageName != string.Empty) {
- baseDir = Directory.GetParent(imageName).FullName;
- var configName = imageName + ".config";
- if (File.Exists(configName))
- return GetPrivatePaths(baseDir, configName);
+ var directoryInfo = Directory.GetParent(imageName);
+ if (directoryInfo is not null) {
+ baseDir = directoryInfo.FullName;
+ var configName = imageName + ".config";
+ if (File.Exists(configName))
+ return GetPrivatePaths(baseDir, configName);
+ }
}
}
catch {
}
- if (baseDir != null)
+ if (baseDir is not null)
return new List { baseDir };
- return new string[0];
+ return Array2.Empty();
}
IEnumerable GetPrivatePaths(string baseDir, string configFileName) {
@@ -702,7 +794,7 @@ IEnumerable GetPrivatePaths(string baseDir, string configFileName) {
doc.Load(XmlReader.Create(xmlStream));
foreach (var tmp in doc.GetElementsByTagName("probing")) {
var probingElem = tmp as XmlElement;
- if (probingElem == null)
+ if (probingElem is null)
continue;
var privatePath = probingElem.GetAttribute("privatePath");
if (string.IsNullOrEmpty(privatePath))
@@ -727,143 +819,5 @@ IEnumerable GetPrivatePaths(string baseDir, string configFileName) {
return searchPaths;
}
-
- ///
- /// Add other common search paths
- ///
- /// A list that gets updated with the new paths
- protected static void AddOtherSearchPaths(IList paths) {
- var dirPF = Environment.GetEnvironmentVariable("ProgramFiles");
- AddOtherAssemblySearchPaths(paths, dirPF);
- var dirPFx86 = Environment.GetEnvironmentVariable("ProgramFiles(x86)");
- if (!StringComparer.OrdinalIgnoreCase.Equals(dirPF, dirPFx86))
- AddOtherAssemblySearchPaths(paths, dirPFx86);
-
- var windir = Environment.GetEnvironmentVariable("WINDIR");
- if (!string.IsNullOrEmpty(windir)) {
- AddIfExists(paths, windir, @"Microsoft.NET\Framework\v1.1.4322");
- AddIfExists(paths, windir, @"Microsoft.NET\Framework\v1.0.3705");
- }
- }
-
- static void AddOtherAssemblySearchPaths(IList paths, string path) {
- if (string.IsNullOrEmpty(path))
- return;
- AddSilverlightDirs(paths, Path.Combine(path, @"Microsoft Silverlight"));
- AddIfExists(paths, path, @"Microsoft SDKs\Silverlight\v2.0\Libraries\Client");
- AddIfExists(paths, path, @"Microsoft SDKs\Silverlight\v2.0\Libraries\Server");
- AddIfExists(paths, path, @"Microsoft SDKs\Silverlight\v2.0\Reference Assemblies");
- AddIfExists(paths, path, @"Microsoft SDKs\Silverlight\v3.0\Libraries\Client");
- AddIfExists(paths, path, @"Microsoft SDKs\Silverlight\v3.0\Libraries\Server");
- AddIfExists(paths, path, @"Microsoft SDKs\Silverlight\v4.0\Libraries\Client");
- AddIfExists(paths, path, @"Microsoft SDKs\Silverlight\v4.0\Libraries\Server");
- AddIfExists(paths, path, @"Microsoft SDKs\Silverlight\v5.0\Libraries\Client");
- AddIfExists(paths, path, @"Microsoft SDKs\Silverlight\v5.0\Libraries\Server");
- AddIfExists(paths, path, @"Microsoft.NET\SDK\CompactFramework\v2.0\WindowsCE");
- AddIfExists(paths, path, @"Microsoft.NET\SDK\CompactFramework\v3.5\WindowsCE");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETFramework\v3.5\Profile\Client");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETCore\v4.5.1");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETCore\v4.5");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETMicroFramework\v3.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETMicroFramework\v4.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETMicroFramework\v4.1");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETMicroFramework\v4.2");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETMicroFramework\v4.3");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETPortable\v4.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\.NETPortable\v4.6");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\v3.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\v3.5");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\Silverlight\v3.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\Silverlight\v4.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\Silverlight\v5.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\WindowsPhone\v8.1");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\Framework\WindowsPhoneApp\v8.1");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\.NETCore\3.259.4.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\.NETCore\3.259.3.1");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\.NETCore\3.78.4.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\.NETCore\3.78.3.1");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\.NETCore\3.7.4.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\.NETCore\3.3.1.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\.NETFramework\v2.0\2.3.0.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.3.0.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.3.1.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.4.0.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\.NETPortable\2.3.5.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\.NETPortable\2.3.5.1");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\.NETPortable\3.47.4.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\2.0\Runtime\v2.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\2.0\Runtime\v4.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\3.0\Runtime\.NETPortable");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\3.0\Runtime\v2.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\FSharp\3.0\Runtime\v4.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\WindowsPowerShell\v1.0");
- AddIfExists(paths, path, @"Reference Assemblies\Microsoft\WindowsPowerShell\3.0");
- AddIfExists(paths, path, @"Microsoft Visual Studio .NET\Common7\IDE\PublicAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio .NET\Common7\IDE\PrivateAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio .NET 2003\Common7\IDE\PublicAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio .NET 2003\Common7\IDE\PrivateAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio 8\Common7\IDE\PublicAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio 11.0\Common7\IDE\PublicAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio 11.0\Common7\IDE\PrivateAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio 12.0\Common7\IDE\PublicAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio 12.0\Common7\IDE\PrivateAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio 14.0\Common7\IDE\PublicAssemblies");
- AddIfExists(paths, path, @"Microsoft Visual Studio 14.0\Common7\IDE\PrivateAssemblies");
- AddIfExists(paths, path, @"Microsoft XNA\XNA Game Studio\v2.0\References\Windows\x86");
- AddIfExists(paths, path, @"Microsoft XNA\XNA Game Studio\v2.0\References\Xbox360");
- AddIfExists(paths, path, @"Microsoft XNA\XNA Game Studio\v3.0\References\Windows\x86");
- AddIfExists(paths, path, @"Microsoft XNA\XNA Game Studio\v3.0\References\Xbox360");
- AddIfExists(paths, path, @"Microsoft XNA\XNA Game Studio\v3.0\References\Zune");
- AddIfExists(paths, path, @"Microsoft XNA\XNA Game Studio\v3.1\References\Windows\x86");
- AddIfExists(paths, path, @"Microsoft XNA\XNA Game Studio\v3.1\References\Xbox360");
- AddIfExists(paths, path, @"Microsoft XNA\XNA Game Studio\v3.1\References\Zune");
- AddIfExists(paths, path, @"Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86");
- AddIfExists(paths, path, @"Microsoft XNA\XNA Game Studio\v4.0\References\Xbox360");
- AddIfExists(paths, path, @"Windows CE Tools\wce500\Windows Mobile 5.0 Pocket PC SDK\Designtimereferences");
- AddIfExists(paths, path, @"Windows CE Tools\wce500\Windows Mobile 5.0 Smartphone SDK\Designtimereferences");
- AddIfExists(paths, path, @"Windows Mobile 5.0 SDK R2\Managed Libraries");
- AddIfExists(paths, path, @"Windows Mobile 6 SDK\Managed Libraries");
- AddIfExists(paths, path, @"Windows Mobile 6.5.3 DTK\Managed Libraries");
- AddIfExists(paths, path, @"Microsoft SQL Server\90\SDK\Assemblies");
- AddIfExists(paths, path, @"Microsoft SQL Server\100\SDK\Assemblies");
- AddIfExists(paths, path, @"Microsoft SQL Server\110\SDK\Assemblies");
- AddIfExists(paths, path, @"Microsoft SQL Server\120\SDK\Assemblies");
- AddIfExists(paths, path, @"Microsoft ASP.NET\ASP.NET MVC 2\Assemblies");
- AddIfExists(paths, path, @"Microsoft ASP.NET\ASP.NET MVC 3\Assemblies");
- AddIfExists(paths, path, @"Microsoft ASP.NET\ASP.NET MVC 4\Assemblies");
- AddIfExists(paths, path, @"Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies");
- AddIfExists(paths, path, @"Microsoft ASP.NET\ASP.NET Web Pages\v2.0\Assemblies");
- AddIfExists(paths, path, @"Microsoft SDKs\F#\3.0\Framework\v4.0");
- }
-
- static void AddSilverlightDirs(IList paths, string basePath) {
- try {
- var di = new DirectoryInfo(basePath);
- foreach (var dir in di.GetDirectories()) {
- if (Regex.IsMatch(dir.Name, @"^\d+(?:\.\d+){3}$"))
- AddIfExists(paths, basePath, dir.Name);
- }
- }
- catch {
- }
- }
-
- static void AddIfExists(IList paths, string basePath, string extraPath) {
- var path = Path.Combine(basePath, extraPath);
- if (Directory.Exists(path))
- paths.Add(path);
- }
}
}
diff --git a/src/DotNet/CallingConvention.cs b/src/DotNet/CallingConvention.cs
index 1ff69a423..da2d6557c 100644
--- a/src/DotNet/CallingConvention.cs
+++ b/src/DotNet/CallingConvention.cs
@@ -26,7 +26,7 @@ public enum CallingConvention : byte {
LocalSig = 0x7,
///
Property = 0x8,
- ///
+ /// Unmanaged calling convention encoded as modopts
Unmanaged = 0x9,
/// generic method instantiation
GenericInst = 0xA,
diff --git a/src/DotNet/CallingConventionSig.cs b/src/DotNet/CallingConventionSig.cs
index 7f825f6a1..98c182d1e 100644
--- a/src/DotNet/CallingConventionSig.cs
+++ b/src/DotNet/CallingConventionSig.cs
@@ -1,13 +1,6 @@
// dnlib: See LICENSE.txt for more info
-using System.Collections.Generic;
-using dnlib.Threading;
-
-#if THREAD_SAFE
-using ThreadSafe = dnlib.Threading.Collections;
-#else
-using ThreadSafe = System.Collections.Generic;
-#endif
+using System.Collections.Generic;
/*
All signature classes:
@@ -37,99 +30,75 @@ public abstract class CallingConventionSig : IContainsGenericParameter {
/// Gets/sets the extra data found after the signature
///
public byte[] ExtraData {
- get { return extraData; }
- set { extraData = value; }
+ get => extraData;
+ set => extraData = value;
}
///
/// Returns true if is set
///
- public bool IsDefault {
- get { return (callingConvention & CallingConvention.Mask) == CallingConvention.Default; }
- }
+ public bool IsDefault => (callingConvention & CallingConvention.Mask) == CallingConvention.Default;
///
/// Returns true if is set
///
- public bool IsC {
- get { return (callingConvention & CallingConvention.Mask) == CallingConvention.C; }
- }
+ public bool IsC => (callingConvention & CallingConvention.Mask) == CallingConvention.C;
///
/// Returns true if is set
///
- public bool IsStdCall {
- get { return (callingConvention & CallingConvention.Mask) == CallingConvention.StdCall; }
- }
+ public bool IsStdCall => (callingConvention & CallingConvention.Mask) == CallingConvention.StdCall;
///
/// Returns true if is set
///
- public bool IsThisCall {
- get { return (callingConvention & CallingConvention.Mask) == CallingConvention.ThisCall; }
- }
+ public bool IsThisCall => (callingConvention & CallingConvention.Mask) == CallingConvention.ThisCall;
///
/// Returns true if is set
///
- public bool IsFastCall {
- get { return (callingConvention & CallingConvention.Mask) == CallingConvention.FastCall; }
- }
+ public bool IsFastCall => (callingConvention & CallingConvention.Mask) == CallingConvention.FastCall;
///
/// Returns true if is set
///
- public bool IsVarArg {
- get { return (callingConvention & CallingConvention.Mask) == CallingConvention.VarArg; }
- }
+ public bool IsVarArg => (callingConvention & CallingConvention.Mask) == CallingConvention.VarArg;
///
/// Returns true if is set
///
- public bool IsField {
- get { return (callingConvention & CallingConvention.Mask) == CallingConvention.Field; }
- }
+ public bool IsField => (callingConvention & CallingConvention.Mask) == CallingConvention.Field;
///
/// Returns true if is set
///
- public bool IsLocalSig {
- get { return (callingConvention & CallingConvention.Mask) == CallingConvention.LocalSig; }
- }
+ public bool IsLocalSig => (callingConvention & CallingConvention.Mask) == CallingConvention.LocalSig;
///
/// Returns true if is set
///
- public bool IsProperty {
- get { return (callingConvention & CallingConvention.Mask) == CallingConvention.Property; }
- }
+ public bool IsProperty => (callingConvention & CallingConvention.Mask) == CallingConvention.Property;
///
/// Returns true if is set
///
- public bool IsUnmanaged {
- get { return (callingConvention & CallingConvention.Mask) == CallingConvention.Unmanaged; }
- }
+ public bool IsUnmanaged => (callingConvention & CallingConvention.Mask) == CallingConvention.Unmanaged;
///
/// Returns true if is set
///
- public bool IsGenericInst {
- get { return (callingConvention & CallingConvention.Mask) == CallingConvention.GenericInst; }
- }
+ public bool IsGenericInst => (callingConvention & CallingConvention.Mask) == CallingConvention.GenericInst;
///
/// Returns true if is set
///
- public bool IsNativeVarArg {
- get { return (callingConvention & CallingConvention.Mask) == CallingConvention.NativeVarArg; }
- }
+ public bool IsNativeVarArg => (callingConvention & CallingConvention.Mask) == CallingConvention.NativeVarArg;
///
/// Gets/sets the bit
///
public bool Generic {
- get { return (callingConvention & CallingConvention.Generic) != 0; }
+ get => (callingConvention & CallingConvention.Generic) != 0;
set {
if (value)
callingConvention |= CallingConvention.Generic;
@@ -142,7 +111,7 @@ public bool Generic {
/// Gets/sets the bit
///
public bool HasThis {
- get { return (callingConvention & CallingConvention.HasThis) != 0; }
+ get => (callingConvention & CallingConvention.HasThis) != 0;
set {
if (value)
callingConvention |= CallingConvention.HasThis;
@@ -155,7 +124,7 @@ public bool HasThis {
/// Gets/sets the bit
///
public bool ExplicitThis {
- get { return (callingConvention & CallingConvention.ExplicitThis) != 0; }
+ get => (callingConvention & CallingConvention.ExplicitThis) != 0;
set {
if (value)
callingConvention |= CallingConvention.ExplicitThis;
@@ -168,7 +137,7 @@ public bool ExplicitThis {
/// Gets/sets the bit
///
public bool ReservedByCLR {
- get { return (callingConvention & CallingConvention.ReservedByCLR) != 0; }
+ get => (callingConvention & CallingConvention.ReservedByCLR) != 0;
set {
if (value)
callingConvention |= CallingConvention.ReservedByCLR;
@@ -180,17 +149,13 @@ public bool ReservedByCLR {
///
/// true if there's an implicit this parameter
///
- public bool ImplicitThis {
- get { return HasThis && !ExplicitThis; }
- }
+ public bool ImplicitThis => HasThis && !ExplicitThis;
///
/// true if this contains a
/// or a .
///
- public bool ContainsGenericParameter {
- get { return TypeHelper.ContainsGenericParameter(this); }
- }
+ public bool ContainsGenericParameter => TypeHelper.ContainsGenericParameter(this);
///
/// Default constructor
@@ -202,16 +167,12 @@ protected CallingConventionSig() {
/// Constructor
///
/// The calling convention
- protected CallingConventionSig(CallingConvention callingConvention) {
- this.callingConvention = callingConvention;
- }
+ protected CallingConventionSig(CallingConvention callingConvention) => this.callingConvention = callingConvention;
///
/// Gets the calling convention
///
- public CallingConvention GetCallingConvention() {
- return callingConvention;
- }
+ public CallingConvention GetCallingConvention() => callingConvention;
}
///
@@ -224,23 +185,21 @@ public sealed class FieldSig : CallingConventionSig {
/// Gets/sets the field type
///
public TypeSig Type {
- get { return type; }
- set { type = value; }
+ get => type;
+ set => type = value;
}
///
/// Default constructor
///
- public FieldSig() {
- this.callingConvention = CallingConvention.Field;
- }
+ public FieldSig() => callingConvention = CallingConvention.Field;
///
/// Constructor
///
/// Field type
public FieldSig(TypeSig type) {
- this.callingConvention = CallingConvention.Field;
+ callingConvention = CallingConvention.Field;
this.type = type;
}
@@ -257,14 +216,10 @@ internal FieldSig(CallingConvention callingConvention, TypeSig type) {
///
/// Clone this
///
- public FieldSig Clone() {
- return new FieldSig(callingConvention, type);
- }
+ public FieldSig Clone() => new FieldSig(callingConvention, type);
///
- public override string ToString() {
- return FullNameCreator.FullName(type == null ? null : type, false);
- }
+ public override string ToString() => FullNameFactory.FullName(type, false, null, null, null, null);
}
///
@@ -274,50 +229,48 @@ public abstract class MethodBaseSig : CallingConventionSig {
///
protected TypeSig retType;
///
- protected ThreadSafe.IList parameters;
+ protected IList parameters;
///
protected uint genParamCount;
///
- protected ThreadSafe.IList paramsAfterSentinel;
+ protected IList paramsAfterSentinel;
///
/// Gets/sets the calling convention
///
public CallingConvention CallingConvention {
- get { return callingConvention; }
- set { callingConvention = value; }
+ get => callingConvention;
+ set => callingConvention = value;
}
///
/// Gets/sets the return type
///
public TypeSig RetType {
- get { return retType; }
- set { retType = value; }
+ get => retType;
+ set => retType = value;
}
///
/// Gets the parameters. This is never null
///
- public ThreadSafe.IList Params {
- get { return parameters; }
- }
+ public IList Params => parameters;
///
/// Gets/sets the generic param count
///
public uint GenParamCount {
- get { return genParamCount; }
- set { genParamCount = value; }
+ get => genParamCount;
+ set => genParamCount = value;
}
///
/// Gets the parameters that are present after the sentinel. Note that this is null
/// if there's no sentinel. It can still be empty even if it's not null.
///
- public ThreadSafe.IList ParamsAfterSentinel {
- get { return paramsAfterSentinel; }
- set { paramsAfterSentinel = value; }
+ public IList ParamsAfterSentinel {
+ get => paramsAfterSentinel;
+ set => paramsAfterSentinel = value;
}
}
@@ -332,26 +285,22 @@ public sealed class MethodSig : MethodBaseSig {
/// and it's a hint to the module writer if it tries to re-use the same token.
///
public uint OriginalToken {
- get { return origToken; }
- set { origToken = value; }
+ get => origToken;
+ set => origToken = value;
}
///
/// Creates a static MethodSig
///
/// Return type
- public static MethodSig CreateStatic(TypeSig retType) {
- return new MethodSig(CallingConvention.Default, 0, retType);
- }
+ public static MethodSig CreateStatic(TypeSig retType) => new MethodSig(CallingConvention.Default, 0, retType);
///
/// Creates a static MethodSig
///
/// Return type
/// Arg type #1
- public static MethodSig CreateStatic(TypeSig retType, TypeSig argType1) {
- return new MethodSig(CallingConvention.Default, 0, retType, argType1);
- }
+ public static MethodSig CreateStatic(TypeSig retType, TypeSig argType1) => new MethodSig(CallingConvention.Default, 0, retType, argType1);
///
/// Creates a static MethodSig
@@ -359,9 +308,7 @@ public static MethodSig CreateStatic(TypeSig retType, TypeSig argType1) {
/// Return type
/// Arg type #1
/// Arg type #2
- public static MethodSig CreateStatic(TypeSig retType, TypeSig argType1, TypeSig argType2) {
- return new MethodSig(CallingConvention.Default, 0, retType, argType1, argType2);
- }
+ public static MethodSig CreateStatic(TypeSig retType, TypeSig argType1, TypeSig argType2) => new MethodSig(CallingConvention.Default, 0, retType, argType1, argType2);
///
/// Creates a static MethodSig
@@ -370,35 +317,27 @@ public static MethodSig CreateStatic(TypeSig retType, TypeSig argType1, TypeSig
/// Arg type #1
/// Arg type #2
/// Arg type #3
- public static MethodSig CreateStatic(TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) {
- return new MethodSig(CallingConvention.Default, 0, retType, argType1, argType2, argType3);
- }
+ public static MethodSig CreateStatic(TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) => new MethodSig(CallingConvention.Default, 0, retType, argType1, argType2, argType3);
///
/// Creates a static MethodSig
///
/// Return type
/// Argument types
- public static MethodSig CreateStatic(TypeSig retType, params TypeSig[] argTypes) {
- return new MethodSig(CallingConvention.Default, 0, retType, argTypes);
- }
+ public static MethodSig CreateStatic(TypeSig retType, params TypeSig[] argTypes) => new MethodSig(CallingConvention.Default, 0, retType, argTypes);
///
/// Creates an instance MethodSig
///
/// Return type
- public static MethodSig CreateInstance(TypeSig retType) {
- return new MethodSig(CallingConvention.Default | CallingConvention.HasThis, 0, retType);
- }
+ public static MethodSig CreateInstance(TypeSig retType) => new MethodSig(CallingConvention.Default | CallingConvention.HasThis, 0, retType);
///
/// Creates an instance MethodSig
///
/// Return type
/// Arg type #1
- public static MethodSig CreateInstance(TypeSig retType, TypeSig argType1) {
- return new MethodSig(CallingConvention.Default | CallingConvention.HasThis, 0, retType, argType1);
- }
+ public static MethodSig CreateInstance(TypeSig retType, TypeSig argType1) => new MethodSig(CallingConvention.Default | CallingConvention.HasThis, 0, retType, argType1);
///
/// Creates an instance MethodSig
@@ -406,9 +345,7 @@ public static MethodSig CreateInstance(TypeSig retType, TypeSig argType1) {
/// Return type
/// Arg type #1
/// Arg type #2
- public static MethodSig CreateInstance(TypeSig retType, TypeSig argType1, TypeSig argType2) {
- return new MethodSig(CallingConvention.Default | CallingConvention.HasThis, 0, retType, argType1, argType2);
- }
+ public static MethodSig CreateInstance(TypeSig retType, TypeSig argType1, TypeSig argType2) => new MethodSig(CallingConvention.Default | CallingConvention.HasThis, 0, retType, argType1, argType2);
///
/// Creates an instance MethodSig
@@ -417,27 +354,21 @@ public static MethodSig CreateInstance(TypeSig retType, TypeSig argType1, TypeSi
/// Arg type #1
/// Arg type #2
/// Arg type #3
- public static MethodSig CreateInstance(TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) {
- return new MethodSig(CallingConvention.Default | CallingConvention.HasThis, 0, retType, argType1, argType2, argType3);
- }
+ public static MethodSig CreateInstance(TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) => new MethodSig(CallingConvention.Default | CallingConvention.HasThis, 0, retType, argType1, argType2, argType3);
///
/// Creates an instance MethodSig
///
/// Return type
/// Argument types
- public static MethodSig CreateInstance(TypeSig retType, params TypeSig[] argTypes) {
- return new MethodSig(CallingConvention.Default | CallingConvention.HasThis, 0, retType, argTypes);
- }
+ public static MethodSig CreateInstance(TypeSig retType, params TypeSig[] argTypes) => new MethodSig(CallingConvention.Default | CallingConvention.HasThis, 0, retType, argTypes);
///
/// Creates a static generic MethodSig
///
/// Number of generic parameters
/// Return type
- public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType) {
- return new MethodSig(CallingConvention.Default | CallingConvention.Generic, genParamCount, retType);
- }
+ public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType) => new MethodSig(CallingConvention.Default | CallingConvention.Generic, genParamCount, retType);
///
/// Creates a static generic MethodSig
@@ -445,9 +376,7 @@ public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType)
/// Number of generic parameters
/// Return type
/// Arg type #1
- public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType, TypeSig argType1) {
- return new MethodSig(CallingConvention.Default | CallingConvention.Generic, genParamCount, retType, argType1);
- }
+ public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType, TypeSig argType1) => new MethodSig(CallingConvention.Default | CallingConvention.Generic, genParamCount, retType, argType1);
///
/// Creates a static generic MethodSig
@@ -456,9 +385,7 @@ public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType,
/// Return type
/// Arg type #1
/// Arg type #2
- public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2) {
- return new MethodSig(CallingConvention.Default | CallingConvention.Generic, genParamCount, retType, argType1, argType2);
- }
+ public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2) => new MethodSig(CallingConvention.Default | CallingConvention.Generic, genParamCount, retType, argType1, argType2);
///
/// Creates a static generic MethodSig
@@ -468,9 +395,7 @@ public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType,
/// Arg type #1
/// Arg type #2
/// Arg type #3
- public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) {
- return new MethodSig(CallingConvention.Default | CallingConvention.Generic, genParamCount, retType, argType1, argType2, argType3);
- }
+ public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) => new MethodSig(CallingConvention.Default | CallingConvention.Generic, genParamCount, retType, argType1, argType2, argType3);
///
/// Creates a static generic MethodSig
@@ -478,18 +403,14 @@ public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType,
/// Number of generic parameters
/// Return type
/// Argument types
- public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType, params TypeSig[] argTypes) {
- return new MethodSig(CallingConvention.Default | CallingConvention.Generic, genParamCount, retType, argTypes);
- }
+ public static MethodSig CreateStaticGeneric(uint genParamCount, TypeSig retType, params TypeSig[] argTypes) => new MethodSig(CallingConvention.Default | CallingConvention.Generic, genParamCount, retType, argTypes);
///
/// Creates an instance generic MethodSig
///
/// Number of generic parameters
/// Return type
- public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType) {
- return new MethodSig(CallingConvention.Default | CallingConvention.HasThis | CallingConvention.Generic, genParamCount, retType);
- }
+ public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType) => new MethodSig(CallingConvention.Default | CallingConvention.HasThis | CallingConvention.Generic, genParamCount, retType);
///
/// Creates an instance generic MethodSig
@@ -497,9 +418,7 @@ public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retTyp
/// Number of generic parameters
/// Return type
/// Arg type #1
- public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType, TypeSig argType1) {
- return new MethodSig(CallingConvention.Default | CallingConvention.HasThis | CallingConvention.Generic, genParamCount, retType, argType1);
- }
+ public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType, TypeSig argType1) => new MethodSig(CallingConvention.Default | CallingConvention.HasThis | CallingConvention.Generic, genParamCount, retType, argType1);
///
/// Creates an instance generic MethodSig
@@ -508,9 +427,7 @@ public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retTyp
/// Return type
/// Arg type #1
/// Arg type #2
- public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2) {
- return new MethodSig(CallingConvention.Default | CallingConvention.HasThis | CallingConvention.Generic, genParamCount, retType, argType1, argType2);
- }
+ public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2) => new MethodSig(CallingConvention.Default | CallingConvention.HasThis | CallingConvention.Generic, genParamCount, retType, argType1, argType2);
///
/// Creates an instance generic MethodSig
@@ -520,9 +437,7 @@ public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retTyp
/// Arg type #1
/// Arg type #2
/// Arg type #3
- public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) {
- return new MethodSig(CallingConvention.Default | CallingConvention.HasThis | CallingConvention.Generic, genParamCount, retType, argType1, argType2, argType3);
- }
+ public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) => new MethodSig(CallingConvention.Default | CallingConvention.HasThis | CallingConvention.Generic, genParamCount, retType, argType1, argType2, argType3);
///
/// Creates an instance generic MethodSig
@@ -530,16 +445,12 @@ public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retTyp
/// Number of generic parameters
/// Return type
/// Argument types
- public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType, params TypeSig[] argTypes) {
- return new MethodSig(CallingConvention.Default | CallingConvention.HasThis | CallingConvention.Generic, genParamCount, retType, argTypes);
- }
+ public static MethodSig CreateInstanceGeneric(uint genParamCount, TypeSig retType, params TypeSig[] argTypes) => new MethodSig(CallingConvention.Default | CallingConvention.HasThis | CallingConvention.Generic, genParamCount, retType, argTypes);
///
/// Default constructor
///
- public MethodSig() {
- this.parameters = ThreadSafeListCreator.Create();
- }
+ public MethodSig() => parameters = new List();
///
/// Constructor
@@ -547,7 +458,7 @@ public MethodSig() {
/// Calling convention
public MethodSig(CallingConvention callingConvention) {
this.callingConvention = callingConvention;
- this.parameters = ThreadSafeListCreator.Create();
+ parameters = new List();
}
///
@@ -558,7 +469,7 @@ public MethodSig(CallingConvention callingConvention) {
public MethodSig(CallingConvention callingConvention, uint genParamCount) {
this.callingConvention = callingConvention;
this.genParamCount = genParamCount;
- this.parameters = ThreadSafeListCreator.Create();
+ parameters = new List();
}
///
@@ -571,7 +482,7 @@ public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSi
this.callingConvention = callingConvention;
this.genParamCount = genParamCount;
this.retType = retType;
- this.parameters = ThreadSafeListCreator.Create();
+ parameters = new List();
}
///
@@ -585,7 +496,7 @@ public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSi
this.callingConvention = callingConvention;
this.genParamCount = genParamCount;
this.retType = retType;
- this.parameters = ThreadSafeListCreator.Create(argType1);
+ parameters = new List { argType1 };
}
///
@@ -600,7 +511,7 @@ public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSi
this.callingConvention = callingConvention;
this.genParamCount = genParamCount;
this.retType = retType;
- this.parameters = ThreadSafeListCreator.Create(argType1, argType2);
+ parameters = new List { argType1, argType2 };
}
///
@@ -616,7 +527,7 @@ public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSi
this.callingConvention = callingConvention;
this.genParamCount = genParamCount;
this.retType = retType;
- this.parameters = ThreadSafeListCreator.Create(argType1, argType2, argType3);
+ parameters = new List { argType1, argType2, argType3 };
}
///
@@ -630,7 +541,7 @@ public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSi
this.callingConvention = callingConvention;
this.genParamCount = genParamCount;
this.retType = retType;
- this.parameters = ThreadSafeListCreator.Create(argTypes);
+ parameters = new List(argTypes);
}
///
@@ -644,7 +555,7 @@ public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSi
this.callingConvention = callingConvention;
this.genParamCount = genParamCount;
this.retType = retType;
- this.parameters = ThreadSafeListCreator.Create(argTypes);
+ parameters = new List(argTypes);
}
///
@@ -659,21 +570,17 @@ public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSi
this.callingConvention = callingConvention;
this.genParamCount = genParamCount;
this.retType = retType;
- this.parameters = ThreadSafeListCreator.Create(argTypes);
- this.paramsAfterSentinel = paramsAfterSentinel == null ? null : ThreadSafeListCreator.Create(paramsAfterSentinel);
+ parameters = new List(argTypes);
+ this.paramsAfterSentinel = paramsAfterSentinel is null ? null : new List(paramsAfterSentinel);
}
///
/// Clone this
///
- public MethodSig Clone() {
- return new MethodSig(callingConvention, genParamCount, retType, parameters, paramsAfterSentinel);
- }
+ public MethodSig Clone() => new MethodSig(callingConvention, genParamCount, retType, parameters, paramsAfterSentinel);
///
- public override string ToString() {
- return FullNameCreator.MethodSigFullName(this);
- }
+ public override string ToString() => FullNameFactory.MethodBaseSigFullName(this, null);
}
///
@@ -684,18 +591,14 @@ public sealed class PropertySig : MethodBaseSig {
/// Creates a static PropertySig
///
/// Return type
- public static PropertySig CreateStatic(TypeSig retType) {
- return new PropertySig(false, retType);
- }
+ public static PropertySig CreateStatic(TypeSig retType) => new PropertySig(false, retType);
///
/// Creates a static PropertySig
///
/// Return type
/// Arg type #1
- public static PropertySig CreateStatic(TypeSig retType, TypeSig argType1) {
- return new PropertySig(false, retType, argType1);
- }
+ public static PropertySig CreateStatic(TypeSig retType, TypeSig argType1) => new PropertySig(false, retType, argType1);
///
/// Creates a static PropertySig
@@ -703,9 +606,7 @@ public static PropertySig CreateStatic(TypeSig retType, TypeSig argType1) {
/// Return type
/// Arg type #1
/// Arg type #2
- public static PropertySig CreateStatic(TypeSig retType, TypeSig argType1, TypeSig argType2) {
- return new PropertySig(false, retType, argType1, argType2);
- }
+ public static PropertySig CreateStatic(TypeSig retType, TypeSig argType1, TypeSig argType2) => new PropertySig(false, retType, argType1, argType2);
///
/// Creates a static PropertySig
@@ -714,35 +615,27 @@ public static PropertySig CreateStatic(TypeSig retType, TypeSig argType1, TypeSi
/// Arg type #1
/// Arg type #2
/// Arg type #3
- public static PropertySig CreateStatic(TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) {
- return new PropertySig(false, retType, argType1, argType2, argType3);
- }
+ public static PropertySig CreateStatic(TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) => new PropertySig(false, retType, argType1, argType2, argType3);
///
/// Creates a static PropertySig
///
/// Return type
/// Argument types
- public static PropertySig CreateStatic(TypeSig retType, params TypeSig[] argTypes) {
- return new PropertySig(false, retType, argTypes);
- }
+ public static PropertySig CreateStatic(TypeSig retType, params TypeSig[] argTypes) => new PropertySig(false, retType, argTypes);
///
/// Creates an instance PropertySig
///
/// Return type
- public static PropertySig CreateInstance(TypeSig retType) {
- return new PropertySig(true, retType);
- }
+ public static PropertySig CreateInstance(TypeSig retType) => new PropertySig(true, retType);
///
/// Creates an instance PropertySig
///
/// Return type
/// Arg type #1
- public static PropertySig CreateInstance(TypeSig retType, TypeSig argType1) {
- return new PropertySig(true, retType, argType1);
- }
+ public static PropertySig CreateInstance(TypeSig retType, TypeSig argType1) => new PropertySig(true, retType, argType1);
///
/// Creates an instance PropertySig
@@ -750,9 +643,7 @@ public static PropertySig CreateInstance(TypeSig retType, TypeSig argType1) {
/// Return type
/// Arg type #1
/// Arg type #2
- public static PropertySig CreateInstance(TypeSig retType, TypeSig argType1, TypeSig argType2) {
- return new PropertySig(true, retType, argType1, argType2);
- }
+ public static PropertySig CreateInstance(TypeSig retType, TypeSig argType1, TypeSig argType2) => new PropertySig(true, retType, argType1, argType2);
///
/// Creates an instance PropertySig
@@ -761,25 +652,21 @@ public static PropertySig CreateInstance(TypeSig retType, TypeSig argType1, Type
/// Arg type #1
/// Arg type #2
/// Arg type #3
- public static PropertySig CreateInstance(TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) {
- return new PropertySig(true, retType, argType1, argType2, argType3);
- }
+ public static PropertySig CreateInstance(TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) => new PropertySig(true, retType, argType1, argType2, argType3);
///
/// Creates an instance PropertySig
///
/// Return type
/// Argument types
- public static PropertySig CreateInstance(TypeSig retType, params TypeSig[] argTypes) {
- return new PropertySig(true, retType, argTypes);
- }
+ public static PropertySig CreateInstance(TypeSig retType, params TypeSig[] argTypes) => new PropertySig(true, retType, argTypes);
///
/// Default constructor
///
public PropertySig() {
- this.callingConvention = CallingConvention.Property;
- this.parameters = ThreadSafeListCreator.Create();
+ callingConvention = CallingConvention.Property;
+ parameters = new List();
}
///
@@ -788,7 +675,7 @@ public PropertySig() {
/// Calling convention (must have Property set)
internal PropertySig(CallingConvention callingConvention) {
this.callingConvention = callingConvention;
- this.parameters = ThreadSafeListCreator.Create();
+ parameters = new List();
}
///
@@ -796,8 +683,8 @@ internal PropertySig(CallingConvention callingConvention) {
///
/// true if instance, false if static
public PropertySig(bool hasThis) {
- this.callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0);
- this.parameters = ThreadSafeListCreator.Create();
+ callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0);
+ parameters = new List();
}
///
@@ -806,9 +693,9 @@ public PropertySig(bool hasThis) {
/// true if instance, false if static
/// Return type
public PropertySig(bool hasThis, TypeSig retType) {
- this.callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0);
+ callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0);
this.retType = retType;
- this.parameters = ThreadSafeListCreator.Create();
+ parameters = new List();
}
///
@@ -818,9 +705,9 @@ public PropertySig(bool hasThis, TypeSig retType) {
/// Return type
/// Arg type #1
public PropertySig(bool hasThis, TypeSig retType, TypeSig argType1) {
- this.callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0);
+ callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0);
this.retType = retType;
- this.parameters = ThreadSafeListCreator.Create(argType1);
+ parameters = new List { argType1 };
}
///
@@ -831,9 +718,9 @@ public PropertySig(bool hasThis, TypeSig retType, TypeSig argType1) {
/// Arg type #1
/// Arg type #2
public PropertySig(bool hasThis, TypeSig retType, TypeSig argType1, TypeSig argType2) {
- this.callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0);
+ callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0);
this.retType = retType;
- this.parameters = ThreadSafeListCreator.Create(argType1, argType2);
+ parameters = new List { argType1, argType2 };
}
///
@@ -845,9 +732,9 @@ public PropertySig(bool hasThis, TypeSig retType, TypeSig argType1, TypeSig argT
/// Arg type #2
/// Arg type #3
public PropertySig(bool hasThis, TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) {
- this.callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0);
+ callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0);
this.retType = retType;
- this.parameters = ThreadSafeListCreator.Create(argType1, argType2, argType3);
+ parameters = new List { argType1, argType2, argType3 };
}
///
@@ -857,9 +744,9 @@ public PropertySig(bool hasThis, TypeSig retType, TypeSig argType1, TypeSig argT
/// Return type
/// Argument types
public PropertySig(bool hasThis, TypeSig retType, params TypeSig[] argTypes) {
- this.callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0);
+ callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0);
this.retType = retType;
- this.parameters = ThreadSafeListCreator.Create(argTypes);
+ parameters = new List(argTypes);
}
///
@@ -874,42 +761,36 @@ internal PropertySig(CallingConvention callingConvention, uint genParamCount, Ty
this.callingConvention = callingConvention;
this.genParamCount = genParamCount;
this.retType = retType;
- this.parameters = ThreadSafeListCreator.Create(argTypes);
- this.paramsAfterSentinel = paramsAfterSentinel == null ? null : ThreadSafeListCreator.Create(paramsAfterSentinel);
+ parameters = new List(argTypes);
+ this.paramsAfterSentinel = paramsAfterSentinel is null ? null : new List(paramsAfterSentinel);
}
///
/// Clone this
///
- public PropertySig Clone() {
- return new PropertySig(callingConvention, genParamCount, retType, parameters, paramsAfterSentinel);
- }
+ public PropertySig Clone() => new PropertySig(callingConvention, genParamCount, retType, parameters, paramsAfterSentinel);
///
- public override string ToString() {
- return FullNameCreator.PropertySigFullName(this);
- }
+ public override string ToString() => FullNameFactory.MethodBaseSigFullName(this, null);
}
///
/// A local variables signature
///
public sealed class LocalSig : CallingConventionSig {
- readonly ThreadSafe.IList locals;
+ readonly IList locals;
///
/// All local types. This is never null.
///
- public ThreadSafe.IList Locals {
- get { return locals; }
- }
+ public IList Locals => locals;
///
/// Default constructor
///
public LocalSig() {
- this.callingConvention = CallingConvention.LocalSig;
- this.locals = ThreadSafeListCreator.Create();
+ callingConvention = CallingConvention.LocalSig;
+ locals = new List();
}
///
@@ -919,7 +800,7 @@ public LocalSig() {
/// Number of locals
internal LocalSig(CallingConvention callingConvention, uint count) {
this.callingConvention = callingConvention;
- this.locals = ThreadSafeListCreator.Create((int)count);
+ locals = new List((int)count);
}
///
@@ -927,8 +808,8 @@ internal LocalSig(CallingConvention callingConvention, uint count) {
///
/// Local type #1
public LocalSig(TypeSig local1) {
- this.callingConvention = CallingConvention.LocalSig;
- this.locals = ThreadSafeListCreator.Create(local1);
+ callingConvention = CallingConvention.LocalSig;
+ locals = new List { local1 };
}
///
@@ -937,8 +818,8 @@ public LocalSig(TypeSig local1) {
/// Local type #1
/// Local type #2
public LocalSig(TypeSig local1, TypeSig local2) {
- this.callingConvention = CallingConvention.LocalSig;
- this.locals = ThreadSafeListCreator.Create(local1, local2);
+ callingConvention = CallingConvention.LocalSig;
+ locals = new List { local1, local2 };
}
///
@@ -948,8 +829,8 @@ public LocalSig(TypeSig local1, TypeSig local2) {
/// Local type #2
/// Local type #3
public LocalSig(TypeSig local1, TypeSig local2, TypeSig local3) {
- this.callingConvention = CallingConvention.LocalSig;
- this.locals = ThreadSafeListCreator.Create(local1, local2, local3);
+ callingConvention = CallingConvention.LocalSig;
+ locals = new List { local1, local2, local3 };
}
///
@@ -957,8 +838,8 @@ public LocalSig(TypeSig local1, TypeSig local2, TypeSig local3) {
///
/// All locals
public LocalSig(params TypeSig[] locals) {
- this.callingConvention = CallingConvention.LocalSig;
- this.locals = ThreadSafeListCreator.Create(locals);
+ callingConvention = CallingConvention.LocalSig;
+ this.locals = new List(locals);
}
///
@@ -966,8 +847,8 @@ public LocalSig(params TypeSig[] locals) {
///
/// All locals
public LocalSig(IList locals) {
- this.callingConvention = CallingConvention.LocalSig;
- this.locals = ThreadSafeListCreator.Create(locals);
+ callingConvention = CallingConvention.LocalSig;
+ this.locals = new List(locals);
}
///
@@ -976,37 +857,33 @@ public LocalSig(IList locals) {
/// All locals (this instance now owns it)
/// Dummy
internal LocalSig(IList locals, bool dummy) {
- this.callingConvention = CallingConvention.LocalSig;
- this.locals = ThreadSafeListCreator.MakeThreadSafe(locals);
+ callingConvention = CallingConvention.LocalSig;
+ this.locals = locals;
}
///
/// Clone this
///
- public LocalSig Clone() {
- return new LocalSig(locals);
- }
+ public LocalSig Clone() => new LocalSig(locals);
}
///
/// An instantiated generic method signature
///
public sealed class GenericInstMethodSig : CallingConventionSig {
- readonly ThreadSafe.IList genericArgs;
+ readonly IList genericArgs;
///
/// Gets the generic arguments (must be instantiated types, i.e., closed types)
///
- public ThreadSafe.IList GenericArguments {
- get { return genericArgs; }
- }
+ public IList GenericArguments => genericArgs;
///
/// Default constructor
///
public GenericInstMethodSig() {
- this.callingConvention = CallingConvention.GenericInst;
- this.genericArgs = ThreadSafeListCreator.Create();
+ callingConvention = CallingConvention.GenericInst;
+ genericArgs = new List();
}
///
@@ -1016,7 +893,7 @@ public GenericInstMethodSig() {
/// Number of generic args
internal GenericInstMethodSig(CallingConvention callingConvention, uint size) {
this.callingConvention = callingConvention;
- this.genericArgs = ThreadSafeListCreator.Create((int)size);
+ genericArgs = new List((int)size);
}
///
@@ -1024,8 +901,8 @@ internal GenericInstMethodSig(CallingConvention callingConvention, uint size) {
///
/// Generic arg #1
public GenericInstMethodSig(TypeSig arg1) {
- this.callingConvention = CallingConvention.GenericInst;
- this.genericArgs = ThreadSafeListCreator.Create(arg1);
+ callingConvention = CallingConvention.GenericInst;
+ genericArgs = new List { arg1 };
}
///
@@ -1034,8 +911,8 @@ public GenericInstMethodSig(TypeSig arg1) {
/// Generic arg #1
/// Generic arg #2
public GenericInstMethodSig(TypeSig arg1, TypeSig arg2) {
- this.callingConvention = CallingConvention.GenericInst;
- this.genericArgs = ThreadSafeListCreator.Create(arg1, arg2);
+ callingConvention = CallingConvention.GenericInst;
+ genericArgs = new List { arg1, arg2 };
}
///
@@ -1045,8 +922,8 @@ public GenericInstMethodSig(TypeSig arg1, TypeSig arg2) {
/// Generic arg #2
/// Generic arg #3
public GenericInstMethodSig(TypeSig arg1, TypeSig arg2, TypeSig arg3) {
- this.callingConvention = CallingConvention.GenericInst;
- this.genericArgs = ThreadSafeListCreator.Create(arg1, arg2, arg3);
+ callingConvention = CallingConvention.GenericInst;
+ genericArgs = new List { arg1, arg2, arg3 };
}
///
@@ -1054,8 +931,8 @@ public GenericInstMethodSig(TypeSig arg1, TypeSig arg2, TypeSig arg3) {
///
/// Generic args
public GenericInstMethodSig(params TypeSig[] args) {
- this.callingConvention = CallingConvention.GenericInst;
- this.genericArgs = ThreadSafeListCreator.Create(args);
+ callingConvention = CallingConvention.GenericInst;
+ genericArgs = new List(args);
}
///
@@ -1063,16 +940,14 @@ public GenericInstMethodSig(params TypeSig[] args) {
///
/// Generic args
public GenericInstMethodSig(IList args) {
- this.callingConvention = CallingConvention.GenericInst;
- this.genericArgs = ThreadSafeListCreator.Create(args);
+ callingConvention = CallingConvention.GenericInst;
+ genericArgs = new List(args);
}
///
/// Clone this
///
- public GenericInstMethodSig Clone() {
- return new GenericInstMethodSig(genericArgs);
- }
+ public GenericInstMethodSig Clone() => new GenericInstMethodSig(genericArgs);
}
public static partial class Extensions {
@@ -1081,72 +956,56 @@ public static partial class Extensions {
///
/// this
/// Field type or null if none
- public static TypeSig GetFieldType(this FieldSig sig) {
- return sig == null ? null : sig.Type;
- }
+ public static TypeSig GetFieldType(this FieldSig sig) => sig?.Type;
///
/// Gets the return type
///
/// this
/// Return type or null if none
- public static TypeSig GetRetType(this MethodBaseSig sig) {
- return sig == null ? null : sig.RetType;
- }
+ public static TypeSig GetRetType(this MethodBaseSig sig) => sig?.RetType;
///
/// Gets the parameters
///
/// this
/// The parameters
- public static IList GetParams(this MethodBaseSig sig) {
- return sig == null ? ThreadSafeListCreator.Create() : sig.Params;
- }
+ public static IList GetParams(this MethodBaseSig sig) => sig?.Params ?? new List();
///
/// Gets the parameter count
///
/// this
/// Parameter count
- public static int GetParamCount(this MethodBaseSig sig) {
- return sig == null ? 0 : sig.Params.Count;
- }
+ public static int GetParamCount(this MethodBaseSig sig) => sig?.Params.Count ?? 0;
///
/// Gets the generic parameter count
///
/// this
/// Generic parameter count
- public static uint GetGenParamCount(this MethodBaseSig sig) {
- return sig == null ? 0 : sig.GenParamCount;
- }
+ public static uint GetGenParamCount(this MethodBaseSig sig) => sig?.GenParamCount ?? 0;
///
/// Gets the parameters after the sentinel
///
/// this
/// Parameters after sentinel or null if none
- public static IList GetParamsAfterSentinel(this MethodBaseSig sig) {
- return sig == null ? null : sig.ParamsAfterSentinel;
- }
+ public static IList GetParamsAfterSentinel(this MethodBaseSig sig) => sig?.ParamsAfterSentinel;
///
/// Gets the locals
///
/// this
/// All locals
- public static IList GetLocals(this LocalSig sig) {
- return sig == null ? ThreadSafeListCreator.Create() : sig.Locals;
- }
+ public static IList GetLocals(this LocalSig sig) => sig?.Locals ?? new List();
///
/// Gets the generic arguments
///
/// this
/// All generic arguments
- public static IList GetGenericArguments(this GenericInstMethodSig sig) {
- return sig == null ? ThreadSafeListCreator.Create() : sig.GenericArguments;
- }
+ public static IList GetGenericArguments(this GenericInstMethodSig sig) => sig?.GenericArguments ?? new List();
///
/// Gets the property
@@ -1154,8 +1013,6 @@ public static IList GetGenericArguments(this GenericInstMethodSig sig)
/// this
/// The type's property or
/// false if input isnull
- public static bool GetIsDefault(this CallingConventionSig sig) {
- return sig == null ? false : sig.IsDefault;
- }
+ public static bool GetIsDefault(this CallingConventionSig sig) => sig?.IsDefault ?? false;
}
}
diff --git a/src/DotNet/ClassLayout.cs b/src/DotNet/ClassLayout.cs
index 8c93448c0..e11c69832 100644
--- a/src/DotNet/ClassLayout.cs
+++ b/src/DotNet/ClassLayout.cs
@@ -1,6 +1,7 @@
// dnlib: See LICENSE.txt for more info
using System;
+using System.Diagnostics;
using dnlib.DotNet.MD;
namespace dnlib.DotNet {
@@ -14,22 +15,20 @@ public abstract class ClassLayout : IMDTokenProvider {
protected uint rid;
///
- public MDToken MDToken {
- get { return new MDToken(Table.ClassLayout, rid); }
- }
+ public MDToken MDToken => new MDToken(Table.ClassLayout, rid);
///
public uint Rid {
- get { return rid; }
- set { rid = value; }
+ get => rid;
+ set => rid = value;
}
///
/// From column ClassLayout.PackingSize
///
public ushort PackingSize {
- get { return packingSize; }
- set { packingSize = value; }
+ get => packingSize;
+ set => packingSize = value;
}
///
protected ushort packingSize;
@@ -38,8 +37,8 @@ public ushort PackingSize {
/// From column ClassLayout.ClassSize
///
public uint ClassSize {
- get { return classSize; }
- set { classSize = value; }
+ get => classSize;
+ set => classSize = value;
}
///
protected uint classSize;
@@ -70,15 +69,10 @@ public ClassLayoutUser(ushort packingSize, uint classSize) {
/// Created from a row in the ClassLayout table
///
sealed class ClassLayoutMD : ClassLayout, IMDTokenProviderMD {
- /// The module where this instance is located
- readonly ModuleDefMD readerModule;
-
readonly uint origRid;
///
- public uint OrigRid {
- get { return origRid; }
- }
+ public uint OrigRid => origRid;
///
/// Constructor
@@ -89,15 +83,17 @@ public uint OrigRid {
/// If is invalid
public ClassLayoutMD(ModuleDefMD readerModule, uint rid) {
#if DEBUG
- if (readerModule == null)
+ if (readerModule is null)
throw new ArgumentNullException("readerModule");
if (readerModule.TablesStream.ClassLayoutTable.IsInvalidRID(rid))
- throw new BadImageFormatException(string.Format("ClassLayout rid {0} does not exist", rid));
+ throw new BadImageFormatException($"ClassLayout rid {rid} does not exist");
#endif
- this.origRid = rid;
+ origRid = rid;
this.rid = rid;
- this.readerModule = readerModule;
- this.classSize = readerModule.TablesStream.ReadClassLayoutRow(origRid, out this.packingSize);
+ bool b = readerModule.TablesStream.TryReadClassLayoutRow(origRid, out var row);
+ Debug.Assert(b);
+ classSize = row.ClassSize;
+ packingSize = row.PackingSize;
}
}
}
diff --git a/src/DotNet/Constant.cs b/src/DotNet/Constant.cs
index b9e28e4e2..9d100067d 100644
--- a/src/DotNet/Constant.cs
+++ b/src/DotNet/Constant.cs
@@ -1,8 +1,9 @@
// dnlib: See LICENSE.txt for more info
using System;
-using System.Text;
+using System.Diagnostics;
using dnlib.DotNet.MD;
+using dnlib.IO;
namespace dnlib.DotNet {
///
@@ -15,22 +16,20 @@ public abstract class Constant : IMDTokenProvider {
protected uint rid;
///
- public MDToken MDToken {
- get { return new MDToken(Table.Constant, rid); }
- }
+ public MDToken MDToken => new MDToken(Table.Constant, rid);
///
public uint Rid {
- get { return rid; }
- set { rid = value; }
+ get => rid;
+ set => rid = value;
}
///
/// From column Constant.Type
///
public ElementType Type {
- get { return type; }
- set { type = value; }
+ get => type;
+ set => type = value;
}
///
protected ElementType type;
@@ -39,8 +38,8 @@ public ElementType Type {
/// From column Constant.Value
///
public object Value {
- get { return value; }
- set { this.value = value; }
+ get => value;
+ set => this.value = value;
}
///
protected object value;
@@ -61,7 +60,7 @@ public ConstantUser() {
///
/// Value
public ConstantUser(object value) {
- this.type = GetElementType(value);
+ type = GetElementType(value);
this.value = value;
}
@@ -76,24 +75,24 @@ public ConstantUser(object value, ElementType type) {
}
static ElementType GetElementType(object value) {
- if (value == null)
+ if (value is null)
return ElementType.Class;
- switch (System.Type.GetTypeCode(value.GetType())) {
- case TypeCode.Boolean: return ElementType.Boolean;
- case TypeCode.Char: return ElementType.Char;
- case TypeCode.SByte: return ElementType.I1;
- case TypeCode.Byte: return ElementType.U1;
- case TypeCode.Int16: return ElementType.I2;
- case TypeCode.UInt16: return ElementType.U2;
- case TypeCode.Int32: return ElementType.I4;
- case TypeCode.UInt32: return ElementType.U4;
- case TypeCode.Int64: return ElementType.I8;
- case TypeCode.UInt64: return ElementType.U8;
- case TypeCode.Single: return ElementType.R4;
- case TypeCode.Double: return ElementType.R8;
- case TypeCode.String: return ElementType.String;
- default: return ElementType.Void;
- }
+ return System.Type.GetTypeCode(value.GetType()) switch {
+ TypeCode.Boolean => ElementType.Boolean,
+ TypeCode.Char => ElementType.Char,
+ TypeCode.SByte => ElementType.I1,
+ TypeCode.Byte => ElementType.U1,
+ TypeCode.Int16 => ElementType.I2,
+ TypeCode.UInt16 => ElementType.U2,
+ TypeCode.Int32 => ElementType.I4,
+ TypeCode.UInt32 => ElementType.U4,
+ TypeCode.Int64 => ElementType.I8,
+ TypeCode.UInt64 => ElementType.U8,
+ TypeCode.Single => ElementType.R4,
+ TypeCode.Double => ElementType.R8,
+ TypeCode.String => ElementType.String,
+ _ => ElementType.Void,
+ };
}
}
@@ -101,15 +100,10 @@ static ElementType GetElementType(object value) {
/// Created from a row in the Constant table
///
sealed class ConstantMD : Constant, IMDTokenProviderMD {
- /// The module where this instance is located
- readonly ModuleDefMD readerModule;
-
readonly uint origRid;
///
- public uint OrigRid {
- get { return origRid; }
- }
+ public uint OrigRid => origRid;
///
/// Constructor
@@ -120,84 +114,84 @@ public uint OrigRid {
/// If is invalid
public ConstantMD(ModuleDefMD readerModule, uint rid) {
#if DEBUG
- if (readerModule == null)
+ if (readerModule is null)
throw new ArgumentNullException("readerModule");
if (readerModule.TablesStream.ConstantTable.IsInvalidRID(rid))
- throw new BadImageFormatException(string.Format("Constant rid {0} does not exist", rid));
+ throw new BadImageFormatException($"Constant rid {rid} does not exist");
#endif
- this.origRid = rid;
+ origRid = rid;
this.rid = rid;
- this.readerModule = readerModule;
- uint value = readerModule.TablesStream.ReadConstantRow(origRid, out this.type);
- this.value = GetValue(this.type, readerModule.BlobStream.ReadNoNull(value));
+ bool b = readerModule.TablesStream.TryReadConstantRow(origRid, out var row);
+ Debug.Assert(b);
+ type = (ElementType)row.Type;
+ var reader = readerModule.BlobStream.CreateReader(row.Value);
+ value = GetValue(type, ref reader);
}
- static object GetValue(ElementType etype, byte[] data) {
+ static object GetValue(ElementType etype, ref DataReader reader) {
switch (etype) {
case ElementType.Boolean:
- if (data == null || data.Length < 1)
+ if (reader.Length < 1)
return false;
- return BitConverter.ToBoolean(data, 0);
+ return reader.ReadBoolean();
case ElementType.Char:
- if (data == null || data.Length < 2)
+ if (reader.Length < 2)
return (char)0;
- return BitConverter.ToChar(data, 0);
+ return reader.ReadChar();
case ElementType.I1:
- if (data == null || data.Length < 1)
+ if (reader.Length < 1)
return (sbyte)0;
- return (sbyte)data[0];
+ return reader.ReadSByte();
case ElementType.U1:
- if (data == null || data.Length < 1)
+ if (reader.Length < 1)
return (byte)0;
- return data[0];
+ return reader.ReadByte();
case ElementType.I2:
- if (data == null || data.Length < 2)
+ if (reader.Length < 2)
return (short)0;
- return BitConverter.ToInt16(data, 0);
+ return reader.ReadInt16();
case ElementType.U2:
- if (data == null || data.Length < 2)
+ if (reader.Length < 2)
return (ushort)0;
- return BitConverter.ToUInt16(data, 0);
+ return reader.ReadUInt16();
case ElementType.I4:
- if (data == null || data.Length < 4)
+ if (reader.Length < 4)
return (int)0;
- return BitConverter.ToInt32(data, 0);
+ return reader.ReadInt32();
case ElementType.U4:
- if (data == null || data.Length < 4)
+ if (reader.Length < 4)
return (uint)0;
- return BitConverter.ToUInt32(data, 0);
+ return reader.ReadUInt32();
case ElementType.I8:
- if (data == null || data.Length < 8)
+ if (reader.Length < 8)
return (long)0;
- return BitConverter.ToInt64(data, 0);
+ return reader.ReadInt64();
case ElementType.U8:
- if (data == null || data.Length < 8)
+ if (reader.Length < 8)
return (ulong)0;
- return BitConverter.ToUInt64(data, 0);
+ return reader.ReadUInt64();
case ElementType.R4:
- if (data == null || data.Length < 4)
+ if (reader.Length < 4)
return (float)0;
- return BitConverter.ToSingle(data, 0);
+ return reader.ReadSingle();
case ElementType.R8:
- if (data == null || data.Length < 8)
+ if (reader.Length < 8)
return (double)0;
- return BitConverter.ToDouble(data, 0);
+ return reader.ReadDouble();
case ElementType.String:
- if (data == null)
- return string.Empty;
- return Encoding.Unicode.GetString(data, 0, data.Length / 2 * 2);
+ return reader.ReadUtf16String((int)(reader.BytesLeft / 2));
case ElementType.Class:
return null;
diff --git a/src/DotNet/CorLibTypes.cs b/src/DotNet/CorLibTypes.cs
index a5fc6948d..8a2f598d9 100644
--- a/src/DotNet/CorLibTypes.cs
+++ b/src/DotNet/CorLibTypes.cs
@@ -27,99 +27,61 @@ public sealed class CorLibTypes : ICorLibTypes {
readonly AssemblyRef corLibAssemblyRef;
///
- public CorLibTypeSig Void {
- get { return typeVoid; }
- }
+ public CorLibTypeSig Void => typeVoid;
///
- public CorLibTypeSig Boolean {
- get { return typeBoolean; }
- }
+ public CorLibTypeSig Boolean => typeBoolean;
///
- public CorLibTypeSig Char {
- get { return typeChar; }
- }
+ public CorLibTypeSig Char => typeChar;
///
- public CorLibTypeSig SByte {
- get { return typeSByte; }
- }
+ public CorLibTypeSig SByte => typeSByte;
///
- public CorLibTypeSig Byte {
- get { return typeByte; }
- }
+ public CorLibTypeSig Byte => typeByte;
///
- public CorLibTypeSig Int16 {
- get { return typeInt16; }
- }
+ public CorLibTypeSig Int16 => typeInt16;
///
- public CorLibTypeSig UInt16 {
- get { return typeUInt16; }
- }
+ public CorLibTypeSig UInt16 => typeUInt16;
///
- public CorLibTypeSig Int32 {
- get { return typeInt32; }
- }
+ public CorLibTypeSig Int32 => typeInt32;
///
- public CorLibTypeSig UInt32 {
- get { return typeUInt32; }
- }
+ public CorLibTypeSig UInt32 => typeUInt32;
///
- public CorLibTypeSig Int64 {
- get { return typeInt64; }
- }
+ public CorLibTypeSig Int64 => typeInt64;
///
- public CorLibTypeSig UInt64 {
- get { return typeUInt64; }
- }
+ public CorLibTypeSig UInt64 => typeUInt64;
///
- public CorLibTypeSig Single {
- get { return typeSingle; }
- }
+ public CorLibTypeSig Single => typeSingle;
///
- public CorLibTypeSig Double {
- get { return typeDouble; }
- }
+ public CorLibTypeSig Double => typeDouble;
///
- public CorLibTypeSig String {
- get { return typeString; }
- }
+ public CorLibTypeSig String => typeString;
///
- public CorLibTypeSig TypedReference {
- get { return typeTypedReference; }
- }
+ public CorLibTypeSig TypedReference => typeTypedReference;
///
- public CorLibTypeSig IntPtr {
- get { return typeIntPtr; }
- }
+ public CorLibTypeSig IntPtr => typeIntPtr;
///
- public CorLibTypeSig UIntPtr {
- get { return typeUIntPtr; }
- }
+ public CorLibTypeSig UIntPtr => typeUIntPtr;
///
- public CorLibTypeSig Object {
- get { return typeObject; }
- }
+ public CorLibTypeSig Object => typeObject;
///
- public AssemblyRef AssemblyRef {
- get { return corLibAssemblyRef; }
- }
+ public AssemblyRef AssemblyRef => corLibAssemblyRef;
///
/// Constructor
@@ -141,9 +103,7 @@ public CorLibTypes(ModuleDef module, AssemblyRef corLibAssemblyRef) {
Initialize();
}
- AssemblyRef CreateCorLibAssemblyRef() {
- return module.UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR20());
- }
+ AssemblyRef CreateCorLibAssemblyRef() => module.UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR20());
void Initialize() {
bool isCorLib = module.Assembly.IsCorLib();
@@ -171,15 +131,13 @@ ITypeDefOrRef CreateCorLibTypeRef(bool isCorLib, string name) {
var tr = new TypeRefUser(module, "System", name, corLibAssemblyRef);
if (isCorLib) {
var td = module.Find(tr);
- if (td != null)
+ if (td is not null)
return td;
}
return module.UpdateRowId(tr);
}
///
- public TypeRef GetTypeRef(string @namespace, string name) {
- return module.UpdateRowId(new TypeRefUser(module, @namespace, name, corLibAssemblyRef));
- }
+ public TypeRef GetTypeRef(string @namespace, string name) => module.UpdateRowId(new TypeRefUser(module, @namespace, name, corLibAssemblyRef));
}
}
diff --git a/src/DotNet/CpuArch.cs b/src/DotNet/CpuArch.cs
new file mode 100644
index 000000000..2e0c27a5d
--- /dev/null
+++ b/src/DotNet/CpuArch.cs
@@ -0,0 +1,427 @@
+// dnlib: See LICENSE.txt for more info
+
+using System;
+using dnlib.DotNet.Writer;
+using dnlib.IO;
+using dnlib.PE;
+
+namespace dnlib.DotNet {
+ enum StubType {
+ Export,
+ EntryPoint,
+ }
+
+ abstract class CpuArch {
+ // To support a new CPU arch, the easiest way is to check coreclr/src/ilasm/writer.cpp or
+ // coreclr/src/dlls/mscorpe/stubs.h, eg. ExportStubAMD64Template, ExportStubX86Template,
+ // ExportStubARMTemplate, ExportStubIA64Template, or use ilasm to generate a file with
+ // exports and check the stub
+ static readonly X86CpuArch x86CpuArch = new X86CpuArch();
+ static readonly X64CpuArch x64CpuArch = new X64CpuArch();
+ static readonly ItaniumCpuArch itaniumCpuArch = new ItaniumCpuArch();
+ static readonly ArmCpuArch armCpuArch = new ArmCpuArch();
+
+ ///
+ /// Gets the required alignment for the stubs, must be a power of 2
+ ///
+ /// Stub type
+ ///
+ public abstract uint GetStubAlignment(StubType stubType);
+
+ ///
+ /// Gets the size of a stub, it doesn't have to be a multiple of
+ ///
+ /// Stub type
+ ///
+ public abstract uint GetStubSize(StubType stubType);
+
+ ///
+ /// Gets the offset of the code (entry point) relative to the start of the stub
+ ///
+ /// Stub type
+ ///
+ public abstract uint GetStubCodeOffset(StubType stubType);
+
+ public static bool TryGetCpuArch(Machine machine, out CpuArch cpuArch) {
+ switch (machine) {
+ case Machine.I386:
+ case Machine.I386_Native_Apple:
+ case Machine.I386_Native_FreeBSD:
+ case Machine.I386_Native_Linux:
+ case Machine.I386_Native_NetBSD:
+ case Machine.I386_Native_Sun:
+ cpuArch = x86CpuArch;
+ return true;
+
+ case Machine.AMD64:
+ case Machine.AMD64_Native_Apple:
+ case Machine.AMD64_Native_FreeBSD:
+ case Machine.AMD64_Native_Linux:
+ case Machine.AMD64_Native_NetBSD:
+ case Machine.AMD64_Native_Sun:
+ cpuArch = x64CpuArch;
+ return true;
+
+ case Machine.IA64:
+ cpuArch = itaniumCpuArch;
+ return true;
+
+ case Machine.ARMNT:
+ case Machine.ARMNT_Native_Apple:
+ case Machine.ARMNT_Native_FreeBSD:
+ case Machine.ARMNT_Native_Linux:
+ case Machine.ARMNT_Native_NetBSD:
+ case Machine.ARMNT_Native_Sun:
+ cpuArch = armCpuArch;
+ return true;
+
+ case Machine.ARM64:
+ case Machine.ARM64_Native_Apple:
+ case Machine.ARM64_Native_FreeBSD:
+ case Machine.ARM64_Native_Linux:
+ case Machine.ARM64_Native_NetBSD:
+ case Machine.ARM64_Native_Sun:
+ //TODO: Support ARM64
+ goto default;
+
+ default:
+ cpuArch = null;
+ return false;
+ }
+ }
+
+ ///
+ /// Gets the RVA of the func field that the stub jumps to
+ ///
+ /// Reader, positioned at the stub func
+ /// PE image
+ /// Updated with RVA of func field
+ ///
+ public bool TryGetExportedRvaFromStub(ref DataReader reader, IPEImage peImage, out uint funcRva) =>
+ TryGetExportedRvaFromStubCore(ref reader, peImage, out funcRva);
+
+ protected abstract bool TryGetExportedRvaFromStubCore(ref DataReader reader, IPEImage peImage, out uint funcRva);
+
+ ///
+ /// Writes stub relocs, if needed
+ ///
+ /// Stub type
+ /// Reloc directory
+ /// The chunk where this stub will be written to
+ /// Offset of this stub in
+ public abstract void WriteStubRelocs(StubType stubType, RelocDirectory relocDirectory, IChunk chunk, uint stubOffset);
+
+ ///
+ /// Writes the stub that jumps to the managed function
+ ///
+ /// Stub type
+ /// Writer
+ /// Image base
+ /// RVA of this stub
+ /// RVA of a pointer-sized field that contains the absolute address of the managed function
+ public abstract void WriteStub(StubType stubType, DataWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva);
+ }
+
+ sealed class X86CpuArch : CpuArch {
+ public override uint GetStubAlignment(StubType stubType) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ return 4;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public override uint GetStubSize(StubType stubType) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ return 2/*padding*/ + 6;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public override uint GetStubCodeOffset(StubType stubType) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ return 2/*padding*/;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ protected override bool TryGetExportedRvaFromStubCore(ref DataReader reader, IPEImage peImage, out uint funcRva) {
+ funcRva = 0;
+
+ // FF25xxxxxxxx jmp DWORD PTR [xxxxxxxx]
+ if (reader.ReadUInt16() != 0x25FF)
+ return false;
+ funcRva = reader.ReadUInt32() - (uint)peImage.ImageNTHeaders.OptionalHeader.ImageBase;
+ return true;
+ }
+
+ public override void WriteStubRelocs(StubType stubType, RelocDirectory relocDirectory, IChunk chunk, uint stubOffset) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ relocDirectory.Add(chunk, stubOffset + 4);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public override void WriteStub(StubType stubType, DataWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ writer.WriteUInt16(0);// padding
+ writer.WriteUInt16(0x25FF);
+ writer.WriteUInt32((uint)imageBase + managedFuncRva);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ }
+
+ sealed class X64CpuArch : CpuArch {
+ public override uint GetStubAlignment(StubType stubType) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ return 4;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public override uint GetStubSize(StubType stubType) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ return 2/*padding*/ + 12;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public override uint GetStubCodeOffset(StubType stubType) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ return 2/*padding*/;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ protected override bool TryGetExportedRvaFromStubCore(ref DataReader reader, IPEImage peImage, out uint funcRva) {
+ funcRva = 0;
+
+ // 48A1xxxxxxxxxxxxxxxx movabs rax,[xxxxxxxxxxxxxxxx]
+ // FFE0 jmp rax
+ if (reader.ReadUInt16() != 0xA148)
+ return false;
+ ulong absAddr = reader.ReadUInt64();
+ if (reader.ReadUInt16() != 0xE0FF)
+ return false;
+ ulong rva = absAddr - peImage.ImageNTHeaders.OptionalHeader.ImageBase;
+ if (rva > uint.MaxValue)
+ return false;
+ funcRva = (uint)rva;
+ return true;
+ }
+
+ public override void WriteStubRelocs(StubType stubType, RelocDirectory relocDirectory, IChunk chunk, uint stubOffset) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ relocDirectory.Add(chunk, stubOffset + 4);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public override void WriteStub(StubType stubType, DataWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ writer.WriteUInt16(0);// padding
+ writer.WriteUInt16(0xA148);
+ writer.WriteUInt64(imageBase + managedFuncRva);
+ writer.WriteUInt16(0xE0FF);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ }
+
+ sealed class ItaniumCpuArch : CpuArch {
+ public override uint GetStubAlignment(StubType stubType) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ return 16;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public override uint GetStubSize(StubType stubType) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ return 0x30;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public override uint GetStubCodeOffset(StubType stubType) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ return 0x20;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ protected override bool TryGetExportedRvaFromStubCore(ref DataReader reader, IPEImage peImage, out uint funcRva) {
+ funcRva = 0;
+
+ // From ExportStubIA64Template in coreclr/src/ilasm/writer.cpp
+ //
+ // ld8 r9 = [gp] ;;
+ // ld8 r10 = [r9],8
+ // nop.i ;;
+ // ld8 gp = [r9]
+ // mov b6 = r10
+ // br.cond.sptk.few b6
+ //
+ // 0x0B, 0x48, 0x00, 0x02, 0x18, 0x10, 0xA0, 0x40,
+ // 0x24, 0x30, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00,
+ // 0x10, 0x08, 0x00, 0x12, 0x18, 0x10, 0x60, 0x50,
+ // 0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0x80, 0x00,
+ // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//address of the template
+ // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 //address of VTFixup slot
+ ulong addrTemplate = reader.ReadUInt64();
+ ulong absAddr = reader.ReadUInt64();
+ reader.Position = (uint)peImage.ToFileOffset((RVA)(addrTemplate - peImage.ImageNTHeaders.OptionalHeader.ImageBase));
+ if (reader.ReadUInt64() != 0x40A010180200480BUL)
+ return false;
+ if (reader.ReadUInt64() != 0x0004000000283024UL)
+ return false;
+ if (reader.ReadUInt64() != 0x5060101812000810UL)
+ return false;
+ if (reader.ReadUInt64() != 0x0080006000038004UL)
+ return false;
+
+ ulong rva = absAddr - peImage.ImageNTHeaders.OptionalHeader.ImageBase;
+ if (rva > uint.MaxValue)
+ return false;
+ funcRva = (uint)rva;
+ return true;
+ }
+
+ public override void WriteStubRelocs(StubType stubType, RelocDirectory relocDirectory, IChunk chunk, uint stubOffset) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ relocDirectory.Add(chunk, stubOffset + 0x20);
+ relocDirectory.Add(chunk, stubOffset + 0x28);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public override void WriteStub(StubType stubType, DataWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ writer.WriteUInt64(0x40A010180200480BUL);
+ writer.WriteUInt64(0x0004000000283024UL);
+ writer.WriteUInt64(0x5060101812000810UL);
+ writer.WriteUInt64(0x0080006000038004UL);
+ writer.WriteUInt64(imageBase + stubRva);
+ writer.WriteUInt64(imageBase + managedFuncRva);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ }
+
+ sealed class ArmCpuArch : CpuArch {
+ public override uint GetStubAlignment(StubType stubType) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ return 4;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public override uint GetStubSize(StubType stubType) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ return 8;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public override uint GetStubCodeOffset(StubType stubType) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ return 0;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ protected override bool TryGetExportedRvaFromStubCore(ref DataReader reader, IPEImage peImage, out uint funcRva) {
+ funcRva = 0;
+
+ // DFF800F0 ldr.w pc,[pc]
+ // xxxxxxxx
+ if (reader.ReadUInt32() != 0xF000F8DF)
+ return false;
+ funcRva = reader.ReadUInt32() - (uint)peImage.ImageNTHeaders.OptionalHeader.ImageBase;
+ return true;
+ }
+
+ public override void WriteStubRelocs(StubType stubType, RelocDirectory relocDirectory, IChunk chunk, uint stubOffset) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ relocDirectory.Add(chunk, stubOffset + 4);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ public override void WriteStub(StubType stubType, DataWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva) {
+ switch (stubType) {
+ case StubType.Export:
+ case StubType.EntryPoint:
+ writer.WriteUInt32(0xF000F8DF);
+ writer.WriteUInt32((uint)imageBase + managedFuncRva);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ }
+}
diff --git a/src/DotNet/CustomAttribute.cs b/src/DotNet/CustomAttribute.cs
index f3bacf34e..377fdf82e 100644
--- a/src/DotNet/CustomAttribute.cs
+++ b/src/DotNet/CustomAttribute.cs
@@ -2,14 +2,6 @@
using System;
using System.Collections.Generic;
-using dnlib.Threading;
-using dnlib.IO;
-
-#if THREAD_SAFE
-using ThreadSafe = dnlib.Threading.Collections;
-#else
-using ThreadSafe = System.Collections.Generic;
-#endif
namespace dnlib.DotNet {
///
@@ -18,96 +10,98 @@ namespace dnlib.DotNet {
public sealed class CustomAttribute : ICustomAttribute {
ICustomAttributeType ctor;
byte[] rawData;
- readonly ThreadSafe.IList arguments;
- readonly ThreadSafe.IList namedArguments;
- IBinaryReader blobReader;
+ readonly IList arguments;
+ readonly IList namedArguments;
+ uint caBlobOffset;
///
/// Gets/sets the custom attribute constructor
///
public ICustomAttributeType Constructor {
- get { return ctor; }
- set { ctor = value; }
+ get => ctor;
+ set => ctor = value;
}
///
/// Gets the attribute type
///
- public ITypeDefOrRef AttributeType {
- get {
- var cat = ctor;
- return cat == null ? null : cat.DeclaringType;
- }
- }
+ public ITypeDefOrRef AttributeType => ctor?.DeclaringType;
///
/// Gets the full name of the attribute type
///
public string TypeFullName {
get {
- var mrCtor = ctor as MemberRef;
- if (mrCtor != null)
+ if (ctor is MemberRef mrCtor)
return mrCtor.GetDeclaringTypeFullName() ?? string.Empty;
- var mdCtor = ctor as MethodDef;
- if (mdCtor != null) {
+ if (ctor is MethodDef mdCtor) {
var declType = mdCtor.DeclaringType;
- if (declType != null)
+ if (declType is not null)
return declType.FullName;
}
return string.Empty;
}
- }
-
+ }
+
+ ///
+ /// Gets the name of the attribute type
+ ///
+ internal string TypeName {
+ get {
+ if (ctor is MemberRef mrCtor)
+ return mrCtor.GetDeclaringTypeName() ?? string.Empty;
+
+ if (ctor is MethodDef mdCtor) {
+ var declType = mdCtor.DeclaringType;
+ if (declType is not null)
+ return declType.Name;
+ }
+
+ return string.Empty;
+ }
+ }
+
///
/// true if the raw custom attribute blob hasn't been parsed
///
- public bool IsRawBlob {
- get { return rawData != null; }
- }
+ public bool IsRawBlob => rawData is not null;
///
/// Gets the raw custom attribute blob or null if the CA was successfully parsed.
///
- public byte[] RawData {
- get { return rawData; }
- }
+ public byte[] RawData => rawData;
///
/// Gets all constructor arguments
///
- public ThreadSafe.IList ConstructorArguments {
- get { return arguments; }
- }
+ public IList ConstructorArguments => arguments;
///
/// true if is not empty
///
- public bool HasConstructorArguments {
- get { return arguments.Count > 0; }
- }
+ public bool HasConstructorArguments => arguments.Count > 0;
///
/// Gets all named arguments (field and property values)
///
- public ThreadSafe.IList NamedArguments {
- get { return namedArguments; }
- }
+ public IList NamedArguments => namedArguments;
///
/// true if is not empty
///
- public bool HasNamedArguments {
- get { return namedArguments.Count > 0; }
- }
+ public bool HasNamedArguments => namedArguments.Count > 0;
///
/// Gets all s that are field arguments
///
public IEnumerable Fields {
get {
- foreach (var namedArg in namedArguments.GetSafeEnumerable()) {
+ var namedArguments = this.namedArguments;
+ int count = namedArguments.Count;
+ for (int i = 0; i < count; i++) {
+ var namedArg = namedArguments[i];
if (namedArg.IsField)
yield return namedArg;
}
@@ -119,29 +113,35 @@ public IEnumerable Fields {
///
public IEnumerable Properties {
get {
- foreach (var namedArg in namedArguments.GetSafeEnumerable()) {
+ var namedArguments = this.namedArguments;
+ int count = namedArguments.Count;
+ for (int i = 0; i < count; i++) {
+ var namedArg = namedArguments[i];
if (namedArg.IsProperty)
yield return namedArg;
}
}
}
+ ///
+ /// Gets the #Blob offset or 0 if unknown
+ ///
+ public uint BlobOffset => caBlobOffset;
+
///
/// Constructor
///
/// Custom attribute constructor
/// Raw custom attribute blob
public CustomAttribute(ICustomAttributeType ctor, byte[] rawData)
- : this(ctor, null, null, null) {
- this.rawData = rawData;
- }
+ : this(ctor, null, null, 0) => this.rawData = rawData;
///
/// Constructor
///
/// Custom attribute constructor
public CustomAttribute(ICustomAttributeType ctor)
- : this(ctor, null, null, null) {
+ : this(ctor, null, null, 0) {
}
///
@@ -169,7 +169,7 @@ public CustomAttribute(ICustomAttributeType ctor, IEnumerable n
/// Constructor arguments or null if none
/// Named arguments or null if none
public CustomAttribute(ICustomAttributeType ctor, IEnumerable arguments, IEnumerable namedArguments)
- : this(ctor, arguments, namedArguments, null) {
+ : this(ctor, arguments, namedArguments, 0) {
}
///
@@ -178,12 +178,12 @@ public CustomAttribute(ICustomAttributeType ctor, IEnumerable argume
/// Custom attribute constructor
/// Constructor arguments or null if none
/// Named arguments or null if none
- /// A reader that returns the original custom attribute blob data
- public CustomAttribute(ICustomAttributeType ctor, IEnumerable arguments, IEnumerable namedArguments, IBinaryReader blobReader) {
+ /// Original custom attribute #Blob offset or 0
+ public CustomAttribute(ICustomAttributeType ctor, IEnumerable arguments, IEnumerable namedArguments, uint caBlobOffset) {
this.ctor = ctor;
- this.arguments = arguments == null ? ThreadSafeListCreator.Create() : ThreadSafeListCreator.Create(arguments);
- this.namedArguments = namedArguments == null ? ThreadSafeListCreator.Create() : ThreadSafeListCreator.Create(namedArguments);
- this.blobReader = blobReader;
+ this.arguments = arguments is null ? new List() : new List(arguments);
+ this.namedArguments = namedArguments is null ? new List() : new List(namedArguments);
+ this.caBlobOffset = caBlobOffset;
}
///
@@ -192,12 +192,12 @@ public CustomAttribute(ICustomAttributeType ctor, IEnumerable argume
/// Custom attribute constructor
/// Constructor arguments. The list is now owned by this instance.
/// Named arguments. The list is now owned by this instance.
- /// A reader that returns the original custom attribute blob data
- internal CustomAttribute(ICustomAttributeType ctor, List arguments, List namedArguments, IBinaryReader blobReader) {
+ /// Original custom attribute #Blob offset or 0
+ internal CustomAttribute(ICustomAttributeType ctor, List arguments, List namedArguments, uint caBlobOffset) {
this.ctor = ctor;
- this.arguments = arguments == null ? ThreadSafeListCreator.Create() : ThreadSafeListCreator.MakeThreadSafe(arguments);
- this.namedArguments = namedArguments == null ? ThreadSafeListCreator.Create() : ThreadSafeListCreator.MakeThreadSafe(namedArguments);
- this.blobReader = blobReader;
+ this.arguments = arguments ?? new List();
+ this.namedArguments = namedArguments ?? new List();
+ this.caBlobOffset = caBlobOffset;
}
///
@@ -205,36 +205,28 @@ internal CustomAttribute(ICustomAttributeType ctor, List arguments,
///
/// Name of field
/// A instance or null if not found
- public CANamedArgument GetField(string name) {
- return GetNamedArgument(name, true);
- }
+ public CANamedArgument GetField(string name) => GetNamedArgument(name, true);
///
/// Gets the field named
///
/// Name of field
/// A instance or null if not found
- public CANamedArgument GetField(UTF8String name) {
- return GetNamedArgument(name, true);
- }
+ public CANamedArgument GetField(UTF8String name) => GetNamedArgument(name, true);
///
/// Gets the property named
///
/// Name of property
/// A instance or null if not found
- public CANamedArgument GetProperty(string name) {
- return GetNamedArgument(name, false);
- }
+ public CANamedArgument GetProperty(string name) => GetNamedArgument(name, false);
///
/// Gets the property named
///
/// Name of property
/// A instance or null if not found
- public CANamedArgument GetProperty(UTF8String name) {
- return GetNamedArgument(name, false);
- }
+ public CANamedArgument GetProperty(UTF8String name) => GetNamedArgument(name, false);
///
/// Gets the property/field named
@@ -243,7 +235,10 @@ public CANamedArgument GetProperty(UTF8String name) {
/// true if it's a field, false if it's a property
/// A instance or null if not found
public CANamedArgument GetNamedArgument(string name, bool isField) {
- foreach (var namedArg in namedArguments.GetSafeEnumerable()) {
+ var namedArguments = this.namedArguments;
+ int count = namedArguments.Count;
+ for (int i = 0; i < count; i++) {
+ var namedArg = namedArguments[i];
if (namedArg.IsField == isField && UTF8String.ToSystemStringOrEmpty(namedArg.Name) == name)
return namedArg;
}
@@ -257,46 +252,18 @@ public CANamedArgument GetNamedArgument(string name, bool isField) {
/// true if it's a field, false if it's a property
/// A instance or null if not found
public CANamedArgument GetNamedArgument(UTF8String name, bool isField) {
- foreach (var namedArg in namedArguments.GetSafeEnumerable()) {
+ var namedArguments = this.namedArguments;
+ int count = namedArguments.Count;
+ for (int i = 0; i < count; i++) {
+ var namedArg = namedArguments[i];
if (namedArg.IsField == isField && UTF8String.Equals(namedArg.Name, name))
return namedArg;
}
return null;
}
- ///
- /// Gets the binary custom attribute data that was used to create this instance.
- ///
- /// Blob of this custom attribute
- public byte[] GetBlob() {
- if (rawData != null)
- return rawData;
- if (blob != null)
- return blob;
-#if THREAD_SAFE
- if (blobReader != null) {
- lock (this) {
-#endif
- if (blobReader != null) {
- blob = blobReader.ReadAllBytes();
- blobReader.Dispose();
- blobReader = null;
- return blob;
- }
-#if THREAD_SAFE
- }
- }
-#endif
- if (blob != null)
- return blob;
- return blob = new byte[0];
- }
- byte[] blob;
-
///
- public override string ToString() {
- return TypeFullName;
- }
+ public override string ToString() => TypeFullName;
}
///
@@ -310,16 +277,16 @@ public struct CAArgument : ICloneable {
/// Gets/sets the argument type
///
public TypeSig Type {
- get { return type; }
- set { type = value; }
+ readonly get => type;
+ set => type = value;
}
///
/// Gets/sets the argument value
///
public object Value {
- get { return value; }
- set { this.value = value; }
+ readonly get => value;
+ set => this.value = value;
}
///
@@ -328,7 +295,7 @@ public object Value {
/// Argument type
public CAArgument(TypeSig type) {
this.type = type;
- this.value = null;
+ value = null;
}
///
@@ -341,34 +308,31 @@ public CAArgument(TypeSig type, object value) {
this.value = value;
}
- object ICloneable.Clone() {
- return Clone();
- }
+ readonly object ICloneable.Clone() => Clone();
///
/// Clones this instance and any s and s
/// referenced from this instance.
///
///
- public CAArgument Clone() {
+ public readonly CAArgument Clone() {
var value = this.value;
if (value is CAArgument)
value = ((CAArgument)value).Clone();
- else if (value is IList) {
- var args = (IList)value;
- var newArgs = ThreadSafeListCreator.Create(args.Count);
- foreach (var arg in args.GetSafeEnumerable())
+ else if (value is IList args) {
+ var newArgs = new List(args.Count);
+ int count = args.Count;
+ for (int i = 0; i < count; i++) {
+ var arg = args[i];
newArgs.Add(arg.Clone());
+ }
value = newArgs;
}
return new CAArgument(type, value);
}
///
- public override string ToString() {
- object v = value;
- return string.Format("{0} ({1})", v == null ? "null" : v, type);
- }
+ public override readonly string ToString() => $"{value ?? "null"} ({type})";
}
///
@@ -384,56 +348,56 @@ public sealed class CANamedArgument : ICloneable {
/// true if it's a field
///
public bool IsField {
- get { return isField; }
- set { isField = value; }
+ get => isField;
+ set => isField = value;
}
///
/// true if it's a property
///
public bool IsProperty {
- get { return !isField; }
- set { isField = !value; }
+ get => !isField;
+ set => isField = !value;
}
///
/// Gets/sets the field/property type
///
public TypeSig Type {
- get { return type; }
- set { type = value; }
+ get => type;
+ set => type = value;
}
///
/// Gets/sets the property/field name
///
public UTF8String Name {
- get { return name; }
- set { name = value; }
+ get => name;
+ set => name = value;
}
///
/// Gets/sets the argument
///
public CAArgument Argument {
- get { return argument; }
- set { argument = value; }
+ get => argument;
+ set => argument = value;
}
///
/// Gets/sets the argument type
///
public TypeSig ArgumentType {
- get { return argument.Type; }
- set { argument.Type = value; }
+ get => argument.Type;
+ set => argument.Type = value;
}
///
/// Gets/sets the argument value
///
public object Value {
- get { return argument.Value; }
- set { argument.Value = value; }
+ get => argument.Value;
+ set => argument.Value = value;
}
///
@@ -446,9 +410,7 @@ public CANamedArgument() {
/// Constructor
///
/// true if field, false if property
- public CANamedArgument(bool isField) {
- this.isField = isField;
- }
+ public CANamedArgument(bool isField) => this.isField = isField;
///
/// Constructor
@@ -486,22 +448,15 @@ public CANamedArgument(bool isField, TypeSig type, UTF8String name, CAArgument a
this.argument = argument;
}
- object ICloneable.Clone() {
- return Clone();
- }
+ object ICloneable.Clone() => Clone();
///
/// Clones this instance and any s referenced from this instance.
///
///
- public CANamedArgument Clone() {
- return new CANamedArgument(isField, type, name, argument.Clone());
- }
+ public CANamedArgument Clone() => new CANamedArgument(isField, type, name, argument.Clone());
///
- public override string ToString() {
- object v = Value;
- return string.Format("({0}) {1} {2} = {3} ({4})", isField ? "field" : "property", type, name, v == null ? "null" : v, ArgumentType);
- }
+ public override string ToString() => $"({(isField ? "field" : "property")}) {type} {name} = {Value ?? "null"} ({ArgumentType})";
}
}
diff --git a/src/DotNet/CustomAttributeCollection.cs b/src/DotNet/CustomAttributeCollection.cs
index a18c333a0..07fba4659 100644
--- a/src/DotNet/CustomAttributeCollection.cs
+++ b/src/DotNet/CustomAttributeCollection.cs
@@ -1,14 +1,14 @@
// dnlib: See LICENSE.txt for more info
-using System.Collections.Generic;
+using System.Collections.Generic;
using dnlib.Utils;
-using dnlib.Threading;
+using System;
namespace dnlib.DotNet {
///
/// Stores s
///
- public class CustomAttributeCollection : LazyList {
+ public class CustomAttributeCollection : LazyList {
///
/// Default constructor
///
@@ -21,7 +21,7 @@ public CustomAttributeCollection() {
/// Initial length of the list
/// Context passed to
/// Delegate instance that returns original values
- public CustomAttributeCollection(int length, object context, MFunc