pax_global_header00006660000000000000000000000064132503366350014520gustar00rootroot0000000000000052 comment=d57237e61feca7cc6a525abd74b31aab07bb96c7 dnlib-2.1_VS2010/000077500000000000000000000000001325033663500133655ustar00rootroot00000000000000dnlib-2.1_VS2010/.editorconfig000066400000000000000000000103671325033663500160510ustar00rootroot00000000000000root = true [*] indent_size = 4 indent_style = tab insert_final_newline = true tab_width = 4 #end_of_line = [*.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}] dotnet_sort_system_directives_first = true dotnet_style_qualification_for_field = false:suggestion dotnet_style_qualification_for_property = false:suggestion dotnet_style_qualification_for_method = false:suggestion dotnet_style_qualification_for_event = false:suggestion dotnet_style_predefined_type_for_locals_parameters_members = true:none dotnet_style_predefined_type_for_member_access = true:none dotnet_style_object_initializer = true:suggestion dotnet_style_collection_initializer = true:suggestion dotnet_style_coalesce_expression = true:suggestion dotnet_style_null_propagation = true:suggestion dotnet_style_explicit_tuple_names = true:suggestion dotnet_separate_import_directive_groups = false dotnet_style_prefer_is_null_check_over_reference_equality_method = false:suggestion dotnet_style_require_accessibility_modifiers = never:info [*.cs] csharp_style_throw_expression = true:suggestion csharp_style_inlined_variable_declaration = true:suggestion csharp_style_var_for_built_in_types = false:none csharp_style_var_when_type_is_apparent = true:suggestion csharp_style_var_elsewhere = true:suggestion csharp_style_conditional_delegate_call = 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_expression_bodied_constructors = 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_expression_bodied_indexers = true:suggestion csharp_style_expression_bodied_accessors = true:suggestion csharp_prefer_braces = false csharp_space_between_method_declaration_name_and_open_parenthesis = false csharp_space_between_method_declaration_parameter_list_parentheses = false csharp_space_between_method_declaration_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_call_empty_parameter_list_parentheses = false csharp_space_after_keywords_in_control_flow_statements = true csharp_space_between_parentheses = csharp_space_after_cast = false csharp_space_around_declaration_statements = false csharp_space_before_open_square_brackets = false csharp_space_between_empty_square_brackets = false csharp_space_between_square_brackets = false csharp_space_after_colon_in_inheritance_clause = true csharp_space_after_comma = true csharp_space_after_dot = false csharp_space_after_semicolon_in_for_statement = true csharp_space_before_colon_in_inheritance_clause = true csharp_space_before_comma = false csharp_space_before_dot = false csharp_space_before_semicolon_in_for_statement = false csharp_space_around_binary_operators = before_and_after csharp_indent_braces = false csharp_indent_block_contents = true csharp_indent_switch_labels = false csharp_indent_case_contents = true csharp_indent_labels = flush_left csharp_preserve_single_line_blocks = true csharp_preserve_single_line_statements = true csharp_new_line_before_open_brace = none csharp_new_line_before_else = true csharp_new_line_before_catch = true csharp_new_line_before_finally = true csharp_new_line_before_members_in_object_initializers = true csharp_new_line_before_members_in_anonymous_types = true csharp_new_line_between_query_expression_clauses = true csharp_indent_case_contents_when_block = false csharp_prefer_inferred_anonymous_type_member_names = true:suggestion csharp_prefer_inferred_tuple_names = true:suggestion csharp_prefer_simple_default_expression = true:suggestion #csharp_preferred_modifier_order = csharp_style_pattern_local_over_anonymous_function = true:suggestion [*.vb] visual_basic_prefer_inferred_anonymous_type_member_names = true:suggestion visual_basic_prefer_inferred_tuple_names = true:suggestion #visual_basic_preferred_modifier_order = dnlib-2.1_VS2010/.gitattributes000066400000000000000000000001151325033663500162550ustar00rootroot00000000000000* text=auto *.cs text diff=csharp *.sln text eol=crlf *.csproj text eol=crlf dnlib-2.1_VS2010/.gitignore000066400000000000000000000001401325033663500153500ustar00rootroot00000000000000*~ */obj/ *.csproj.user *.sdf *.opensdf *.suo /.vs/ /Debug/ /Release/ /Examples/bin/ *.tmp_proj dnlib-2.1_VS2010/Examples/000077500000000000000000000000001325033663500151435ustar00rootroot00000000000000dnlib-2.1_VS2010/Examples/Example1.cs000066400000000000000000000026241325033663500171520ustar00rootroot00000000000000using System; using dnlib.DotNet; namespace dnlib.Examples { // This example will open mscorlib.dll and then print out all types // in the assembly, including the number of methods, fields, properties // and events each type has. public class Example1 { public static void Run() { // Load mscorlib.dll string filename = typeof(void).Module.FullyQualifiedName; ModuleDefMD 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()) { totalNumTypes++; Console.WriteLine(); Console.WriteLine("Type: {0}", type.FullName); if (type.BaseType != null) Console.WriteLine(" Base type: {0}", type.BaseType.FullName); Console.WriteLine(" Methods: {0}", type.Methods.Count); Console.WriteLine(" Fields: {0}", type.Fields.Count); Console.WriteLine(" Properties: {0}", type.Properties.Count); Console.WriteLine(" Events: {0}", type.Events.Count); Console.WriteLine(" Nested types: {0}", type.NestedTypes.Count); if (type.Interfaces.Count > 0) { Console.WriteLine(" Interfaces:"); foreach (InterfaceImpl iface in type.Interfaces) Console.WriteLine(" {0}", iface.Interface.FullName); } } Console.WriteLine(); Console.WriteLine("Total number of types: {0}", totalNumTypes); } } } dnlib-2.1_VS2010/Examples/Example2.cs000066400000000000000000000051341325033663500171520ustar00rootroot00000000000000using dnlib.DotNet; using dnlib.DotNet.Emit; namespace dnlib.Examples { public class Example2 { // This will open the current assembly, add a new class and method to it, // and then save the assembly to disk. public static void Run() { // Open the current module ModuleDefMD mod = ModuleDefMD.Load(typeof(Example2).Module); // Create a new public class that derives from System.Object TypeDef type1 = new TypeDefUser("My.Namespace", "MyType", mod.CorLibTypes.Object.TypeDefOrRef); type1.Attributes = TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.AnsiClass; // Make sure to add it to the module or any other type in the module. This is // not a nested type, so add it to mod.Types. mod.Types.Add(type1); // Create a public static System.Int32 field called MyField FieldDef field1 = new FieldDefUser("MyField", new FieldSig(mod.CorLibTypes.Int32), FieldAttributes.Public | FieldAttributes.Static); // Add it to the type we created earlier type1.Fields.Add(field1); // 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", 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(); 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); body.Variables.Add(local1); // Add the instructions, and use the useless local body.Instructions.Add(OpCodes.Ldarg_0.ToInstruction()); body.Instructions.Add(OpCodes.Ldarg_1.ToInstruction()); body.Instructions.Add(OpCodes.Add.ToInstruction()); body.Instructions.Add(OpCodes.Ldsfld.ToInstruction(field1)); body.Instructions.Add(OpCodes.Add.ToInstruction()); body.Instructions.Add(OpCodes.Stloc.ToInstruction(local1)); body.Instructions.Add(OpCodes.Ldloc.ToInstruction(local1)); body.Instructions.Add(OpCodes.Ret.ToInstruction()); // Save the assembly to a file on disk mod.Write(@"C:\saved-assembly.dll"); } } } dnlib-2.1_VS2010/Examples/Example3.cs000066400000000000000000000057311325033663500171560ustar00rootroot00000000000000using System; using System.Text; using dnlib.DotNet; using dnlib.DotNet.Emit; namespace dnlib.Examples { // This example creates a new assembly and saves it to disk. // This is what it will look like if you decompile it: // // using System; // namespace My.Namespace // { // internal class Startup // { // private static int Main(string[] args) // { // Console.WriteLine("Hello World!"); // return 0; // } // } // } 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"); // 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); asm.Modules.Add(mod); // Add a .NET resource byte[] resourceData = Encoding.UTF8.GetBytes("Hello, world!"); mod.Resources.Add(new EmbeddedResource("My.Resource", resourceData, ManifestResourceAttributes.Private)); // Add the startup type. It derives from System.Object. TypeDef 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", MethodSig.CreateStatic(mod.CorLibTypes.Int32, new SZArraySig(mod.CorLibTypes.String))); entryPoint.Attributes = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot; entryPoint.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed; // Name the 1st argument (argument 0 is the return type) entryPoint.ParamDefs.Add(new ParamDefUser("args", 1)); // Add the method to the startup type startUpType.Methods.Add(entryPoint); // Set module entry point mod.EntryPoint = entryPoint; // Create a TypeRef to System.Console TypeRef 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", MethodSig.CreateStatic(mod.CorLibTypes.Void, mod.CorLibTypes.String), consoleRef); // Add a CIL method body to the entry point method CilBody epBody = new CilBody(); entryPoint.Body = epBody; epBody.Instructions.Add(OpCodes.Ldstr.ToInstruction("Hello World!")); epBody.Instructions.Add(OpCodes.Call.ToInstruction(consoleWrite1)); epBody.Instructions.Add(OpCodes.Ldc_I4_0.ToInstruction()); epBody.Instructions.Add(OpCodes.Ret.ToInstruction()); // Save the assembly to a file on disk mod.Write(@"C:\saved-assembly.exe"); } } } dnlib-2.1_VS2010/Examples/Example4.cs000066400000000000000000000156311325033663500171570ustar00rootroot00000000000000using System; using dnlib.DotNet; using dnlib.DotNet.Emit; /* This example shows how to create an assembly from scratch and create two instances by calling their constructors. One default constructor and another one taking two arguments. ILSpy output of created file: using System; namespace Ctor.Test { internal class BaseClass { public BaseClass() { Console.WriteLine("BaseClass: Default .ctor called", null); } } internal class Main : BaseClass { public static void Main() { new Main(); new Main(12345, null); } public Main() { Console.WriteLine("Default .ctor called", null); } public Main(int count, string name) { Console.WriteLine(".ctor(Int32) called with arg {0}", count); } } } peverify output: C:\>peverify ctor-test.exe /IL /MD Microsoft (R) .NET Framework PE Verifier. Version 4.0.30319.1 Copyright (c) Microsoft Corporation. All rights reserved. All Classes and Methods in ctor-test.exe Verified. Output of program: C:\>ctor-test.exe BaseClass: Default .ctor called Default .ctor called BaseClass: Default .ctor called .ctor(Int32) called with arg 12345 */ namespace dnlib.Examples { public class Example4 { public static void Run() { // This is the file that will be created string newFileName = @"C:\ctor-test.exe"; // Create the module var mod = new ModuleDefUser("ctor-test", Guid.NewGuid(), new AssemblyRefUser(new AssemblyNameInfo(typeof(int).Assembly.GetName().FullName))); // It's a console app mod.Kind = ModuleKind.Console; // Create the assembly and add the created module to it new AssemblyDefUser("ctor-test", new Version(1, 2, 3, 4)).Modules.Add(mod); // Create System.Console type reference var systemConsole = mod.CorLibTypes.GetTypeRef("System", "Console"); // Create 'void System.Console.WriteLine(string,object)' method reference var writeLine2 = new MemberRefUser(mod, "WriteLine", MethodSig.CreateStatic(mod.CorLibTypes.Void, mod.CorLibTypes.String, mod.CorLibTypes.Object), systemConsole); // Create System.Object::.ctor method reference. This is the default constructor var objectCtor = new MemberRefUser(mod, ".ctor", MethodSig.CreateInstance(mod.CorLibTypes.Void), mod.CorLibTypes.Object.TypeDefOrRef); CilBody body; // Create the base class var bclass = new TypeDefUser("Ctor.Test", "BaseClass", mod.CorLibTypes.Object.TypeDefOrRef); // Add it to the module mod.Types.Add(bclass); // Create Ctor.Test.BaseClass constructor: BaseClass() var bctor = new MethodDefUser(".ctor", MethodSig.CreateInstance(mod.CorLibTypes.Void), MethodImplAttributes.IL | MethodImplAttributes.Managed, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); // Add the method to BaseClass bclass.Methods.Add(bctor); // Create method body and add a few instructions bctor.Body = body = new CilBody(); // Make sure we call the base class' constructor body.Instructions.Add(OpCodes.Ldarg_0.ToInstruction()); body.Instructions.Add(OpCodes.Call.ToInstruction(objectCtor)); body.Instructions.Add(OpCodes.Ldstr.ToInstruction("BaseClass: Default .ctor called")); body.Instructions.Add(OpCodes.Ldnull.ToInstruction()); body.Instructions.Add(OpCodes.Call.ToInstruction(writeLine2)); body.Instructions.Add(OpCodes.Ret.ToInstruction()); // Create the Ctor.Test.Main type which derives from Ctor.Test.BaseClass var main = new TypeDefUser("Ctor.Test", "Main", bclass); // Add it to the module mod.Types.Add(main); // Create the static 'void Main()' method var entryPoint = new MethodDefUser("Main", MethodSig.CreateStatic(mod.CorLibTypes.Void), MethodImplAttributes.IL | MethodImplAttributes.Managed, MethodAttributes.Public | MethodAttributes.Static); // Set entry point to entryPoint and add it as a Ctor.Test.Main method mod.EntryPoint = entryPoint; main.Methods.Add(entryPoint); // Create first Ctor.Test.Main constructor: Main() var ctor0 = new MethodDefUser(".ctor", MethodSig.CreateInstance(mod.CorLibTypes.Void), MethodImplAttributes.IL | MethodImplAttributes.Managed, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); // Add the method to Main main.Methods.Add(ctor0); // Create method body and add a few instructions ctor0.Body = body = new CilBody(); // Make sure we call the base class' constructor body.Instructions.Add(OpCodes.Ldarg_0.ToInstruction()); body.Instructions.Add(OpCodes.Call.ToInstruction(bctor)); body.Instructions.Add(OpCodes.Ldstr.ToInstruction("Default .ctor called")); body.Instructions.Add(OpCodes.Ldnull.ToInstruction()); body.Instructions.Add(OpCodes.Call.ToInstruction(writeLine2)); body.Instructions.Add(OpCodes.Ret.ToInstruction()); // Create second Ctor.Test.Main constructor: Main(int,string) var ctor1 = new MethodDefUser(".ctor", MethodSig.CreateInstance(mod.CorLibTypes.Void, mod.CorLibTypes.Int32, mod.CorLibTypes.String), MethodImplAttributes.IL | MethodImplAttributes.Managed, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); // Add the method to Main main.Methods.Add(ctor1); // Create names for the arguments. This is optional. Since this is an instance method // (it's a constructor), the first arg is the 'this' pointer. The normal arguments // begin at index 1. ctor1.Parameters[1].CreateParamDef(); ctor1.Parameters[1].ParamDef.Name = "count"; ctor1.Parameters[2].CreateParamDef(); ctor1.Parameters[2].ParamDef.Name = "name"; // Create method body and add a few instructions ctor1.Body = body = new CilBody(); // Make sure we call the base class' constructor body.Instructions.Add(OpCodes.Ldarg_0.ToInstruction()); body.Instructions.Add(OpCodes.Call.ToInstruction(bctor)); body.Instructions.Add(OpCodes.Ldstr.ToInstruction(".ctor(Int32) called with arg {0}")); body.Instructions.Add(OpCodes.Ldarg_1.ToInstruction()); body.Instructions.Add(OpCodes.Box.ToInstruction(mod.CorLibTypes.Int32)); body.Instructions.Add(OpCodes.Call.ToInstruction(writeLine2)); body.Instructions.Add(OpCodes.Ret.ToInstruction()); // Create the entry point method body and add instructions to allocate a new Main() // object and call the two created ctors. entryPoint.Body = body = new CilBody(); body.Instructions.Add(OpCodes.Newobj.ToInstruction(ctor0)); body.Instructions.Add(OpCodes.Pop.ToInstruction()); body.Instructions.Add(OpCodes.Ldc_I4.ToInstruction(12345)); body.Instructions.Add(OpCodes.Ldnull.ToInstruction()); body.Instructions.Add(OpCodes.Newobj.ToInstruction(ctor1)); body.Instructions.Add(OpCodes.Pop.ToInstruction()); body.Instructions.Add(OpCodes.Ret.ToInstruction()); // Save the assembly mod.Write(newFileName); } } } dnlib-2.1_VS2010/Examples/Example5.cs000066400000000000000000000022311325033663500171500ustar00rootroot00000000000000using System; using System.IO; using dnlib.DotNet; using dnlib.PE; using dnlib.IO; namespace dnlib.Examples { /// /// Dumps all PE sections to disk /// public class Example5 { public static void Run() { string sectionFileName = @"c:\section{0}.bin"; // Open the current mscorlib var mod = ModuleDefMD.Load(typeof(int).Module); // Get PE image interface var peImage = mod.MetaData.PEImage; // Print some info Console.WriteLine("Machine: {0}", peImage.ImageNTHeaders.FileHeader.Machine); Console.WriteLine("Characteristics: {0}", peImage.ImageNTHeaders.FileHeader.Characteristics); Console.WriteLine("Dumping all sections"); 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); // 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()); } } } } dnlib-2.1_VS2010/Examples/Example6.cs000066400000000000000000000076251325033663500171650ustar00rootroot00000000000000using System; using System.IO; using dnlib.DotNet; using dnlib.DotNet.MD; using dnlib.DotNet.Writer; using dnlib.IO; using dnlib.PE; namespace dnlib.Examples { /// /// This example shows how to create 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(); } void DoIt() { string destFileName = @"c:\output.dll"; // Open the current module var mod = ModuleDefMD.Load(typeof(Example6).Module); // Create the writer options var opts = new ModuleWriterOptions(mod); // Add a listener that gets notified during the writing process opts.Listener = this; // 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 opts.PEHeadersOptions.NumberOfRvaAndSizes = 13; // Add extra data. This will break most libraries that open .NET assemblies. // Any value can be written here. 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 ")); // Write the module. The listener will get notified, see OnWriterEvent() below mod.Write(destFileName, opts); } // A simple heap (must implement the IHeap interface). It just writes 10 bytes to the file. class MyHeap : IHeap { string name; FileOffset offset; RVA rva; // 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; } // 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 void SetReadOnly() { } public FileOffset FileOffset { get { return offset; } } public RVA RVA { get { return 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); } } // Gets notified during module writing public void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) { switch (evt) { case ModuleWriterEvent.PESectionsCreated: // Add a PE section var sect1 = new PESection(".dummy", 0x40000040); writer.Sections.Add(sect1); // Let's add data sect1.Add(new ByteArrayChunk(new byte[123]), 4); sect1.Add(new ByteArrayChunk(new byte[10]), 4); break; 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()) { Console.WriteLine("TYPE: {0:X8} -> {1:X8} {2}", type.MDToken.Raw, new MDToken(Table.TypeDef, 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, method.FullName); } break; default: break; } } } } dnlib-2.1_VS2010/Examples/Examples.csproj000066400000000000000000000046641325033663500201550ustar00rootroot00000000000000 Debug x86 8.0.30703 2.0 {F27E72B5-C4BD-40BF-AD19-4C8A99B55872} Exe 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 {FDFC1237-143F-4919-8318-4926901F4639} dnlib dnlib-2.1_VS2010/Examples/Program.cs000066400000000000000000000004151325033663500171010ustar00rootroot00000000000000namespace dnlib.Examples { class Program { static void Main(string[] args) { // Just uncomment whatever you want to debug // Example1.Run(); // Example2.Run(); // Example3.Run(); // Example4.Run(); // Example5.Run(); Example6.Run(); } } } dnlib-2.1_VS2010/Examples/Properties/000077500000000000000000000000001325033663500172775ustar00rootroot00000000000000dnlib-2.1_VS2010/Examples/Properties/AssemblyInfo.cs000066400000000000000000000010211325033663500222130ustar00rootroot00000000000000using 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")] dnlib-2.1_VS2010/LICENSE.txt000066400000000000000000000025171325033663500152150ustar00rootroot00000000000000dnlib: .NET assembly library https://github.com/0xd4d/dnlib Copyright (C) 2012-2018 de4dot@gmail.com Contributors ------------ Ki, "yck1509 ", https://github.com/yck1509 kiootic, "kiootic ", https://github.com/kiootic SlowLogicBoy, https://github.com/SlowLogicBoy MIT LICENSE ----------- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. dnlib-2.1_VS2010/README.md000066400000000000000000000467431325033663500146620ustar00rootroot00000000000000.NET module/assembly reader/writer library written for [de4dot](https://github.com/0xd4d/de4dot/). 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 other applications using dnlib, see [dnSpy](https://github.com/0xd4d/dnSpy) and [ConfuserEx](https://github.com/yck1509/ConfuserEx/) (a .NET obfuscator). They use many of the more advanced features of dnlib. Have a look at ConfuserEx' writer code which gets executed during the assembly writing process. Want to say thanks? Click the star at the top of the page. 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. 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: ```csharp 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. Read a .NET module from a file: ```csharp ModuleDefMD module = ModuleDefMD.Load(@"C:\path\to\file.exe"); ``` Read a .NET module from a byte array: ```csharp byte[] data = System.IO.File.ReadAllBytes(@"C:\path\of\file.dll"); ModuleDefMD module = ModuleDefMD.Load(data); ``` You can also pass in a Stream instance, an address in memory (HINSTANCE) or even a System.Reflection.Module instance: ```csharp System.Reflection.Module reflectionModule = typeof(void).Module; // Get mscorlib.dll's module ModuleDefMD module = ModuleDefMD.Load(reflectionModule); ``` To get the assembly, use its Assembly property: ```csharp AssemblyDef asm = module.Assembly; Console.WriteLine("Assembly: {0}", asm); ``` Saving a .NET assembly/module ----------------------------- Use `module.Write()`. It can save the assembly to a file or a Stream. ```csharp module.Write(@"C:\saved-assembly.dll"); ``` If it's a C++/CLI assembly, you should use `NativeWrite()` ```csharp module.NativeWrite(@"C:\saved-assembly.dll"); ``` To detect it at runtime, use this code: ```csharp 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"); } else { // This assembly has native code (eg. C++/CLI) module.NativeWrite(@"C:\saved-assembly.dll"); } ``` PDB files --------- 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. 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. ```csharp var mod = ModuleDefMD.Load(@"C:\myfile.dll"); // ... var wopts = new dnlib.DotNet.Writer.ModuleWriterOptions(mod); wopts.WritePdb = true; // wopts.PdbFileName = @"C:\out2.pdb"; // Set other file name mod.Write(@"C:\out.dll", wopts); ``` dnlib supports Windows PDBs, portable PDBs and embedded portable PDBs. Strong name sign an assembly ---------------------------- Use the following code to strong name sign the assembly when saving it: ```csharp using dnlib.DotNet.Writer; ... // Open or create an assembly ModuleDef mod = ModuleDefMD.Load(.....); // Create writer options var opts = new ModuleWriterOptions(mod); // Open or create the strong name key var signatureKey = new StrongNameKey(@"c:\my\file.snk"); // This method will initialize the required properties opts.InitializeStrongNameSigning(mod, signatureKey); // Write and strong name sign the assembly mod.Write(@"C:\out\file.dll", opts); ``` 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. Enhanced strong name signing without key migration: ```csharp using dnlib.DotNet.Writer; ... // Open or create an assembly ModuleDef mod = ModuleDefMD.Load(....); // Open or create the signature keys var signatureKey = new StrongNameKey(....); var signaturePubKey = new StrongNamePublicKey(....); // Create module writer options var opts = new ModuleWriterOptions(mod); // This method will initialize the required properties opts.InitializeEnhancedStrongNameSigning(mod, signatureKey, signaturePubKey); // Write and strong name sign the assembly mod.Write(@"C:\out\file.dll", opts); ``` Enhanced strong name signing with key migration: ```csharp using dnlib.DotNet.Writer; ... // Open or create an assembly ModuleDef mod = ModuleDefMD.Load(....); // Open or create the identity and signature keys var signatureKey = new StrongNameKey(....); var signaturePubKey = new StrongNamePublicKey(....); var identityKey = new StrongNameKey(....); var identityPubKey = new StrongNamePublicKey(....); // Create module writer options var opts = new ModuleWriterOptions(mod); // This method will initialize the required properties and add // the required attribute to the assembly. opts.InitializeEnhancedStrongNameSigning(mod, signatureKey, signaturePubKey, identityKey, identityPubKey); // Write and strong name sign the assembly 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. 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. - It must be a DLL file (see `ModuleWriterOptions.PEHeadersOptions.Characteristics`). The file will fail to load at runtime if it's an EXE file. 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`. 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`. :) `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. `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. `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`. `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: ```csharp ModuleDef mod = ....; // Create a byte[] SZArraySig array1 = new SZArraySig(mod.CorLibTypes.Byte); // Create an int[][] SZArraySig array2 = new SZArraySig(new SZArraySig(mod.CorLibTypes.Int32)); // Create an int[,] ArraySig array3 = new ArraySig(mod.CorLibTypes.Int32, 2); // Create an int[*] (one-dimensional array) ArraySig array4 = new ArraySig(mod.CorLibTypes.Int32, 1); // Create a Stream[]. Stream is a reference class so it must be enclosed in a ClassSig. // If it were a value type, you would use ValueTypeSig instead. TypeRef stream = new TypeRefUser(mod, "System.IO", "Stream", mod.CorLibTypes.AssemblyRef); 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: ```csharp // array5 is defined above ITypeDefOrRef type1 = array5.ToTypeDefOrRef(); TypeSig type2 = type1.ToTypeSig(); ``` 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. Metadata table classes ---------------------- Here's a list of the most common metadata table classes `AssemblyDef` is the assembly class. `AssemblyRef` is an assembly reference. `EventDef` is an event definition. Owned by a `TypeDef`. `FieldDef` is a field definition. Owned by a `TypeDef`. `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. `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. `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. `TypeRef` is a type reference. Usually to a type in another assembly. `TypeSpec` is a type specification, eg. an array, generic type, etc. Method classes -------------- 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`. 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`. 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. ```csharp // Compare two types TypeRef type1 = ...; TypeDef type2 = ...; if (new SigComparer().Equals(type1, type2)) Console.WriteLine("They're equal"); // Use the type equality comparer Dictionary dict = new Dictionary(TypeEqualityComparer.Instance); TypeDef type1 = ...; dict.Add(type1, 10); // Compare a `TypeRef` with a `System.Type` TypeRef type1 = ...; if (new SigComparer().Equals(type1, typeof(int))) Console.WriteLine("They're equal"); ``` 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. `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. `LinkedResource` is a reference to a resource on disk. 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. 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. 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. 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. ```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. ```csharp ModuleDefMD mod = ModuleDefMD.Load(...); mod.Context = modCtx; // Use the previously created (and shared) context mod.Context.AssemblyResolver.AddToCache(mod); ``` Resolving types, methods, etc from metadata tokens -------------------------------------------------- `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.: ```csharp 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. ```csharp Importer importer = new Importer(mod); ITypeDefOrRef consoleRef = importer.Import(typeof(System.Console)); IMethod writeLine = importer.Import(typeof(System.Console).GetMethod("WriteLine")); ``` 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. 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. 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. 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 using dnlib.DotNet.MD; // ... ModuleDefMD mod = ModuleDefMD.Load(...); 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`. dnlib-2.1_VS2010/dnlib.netstandard.sln000066400000000000000000000021601325033663500175000ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27130.2010 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dnlib.netstandard", "src\dnlib.netstandard.csproj", "{80695BC3-65CA-403E-B161-57D4F6EC5CC3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {80695BC3-65CA-403E-B161-57D4F6EC5CC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {80695BC3-65CA-403E-B161-57D4F6EC5CC3}.Debug|Any CPU.Build.0 = Debug|Any CPU {80695BC3-65CA-403E-B161-57D4F6EC5CC3}.Release|Any CPU.ActiveCfg = Release|Any CPU {80695BC3-65CA-403E-B161-57D4F6EC5CC3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DA3B4267-5AB5-4A1D-A0D5-CF49A2882567} EndGlobalSection EndGlobal dnlib-2.1_VS2010/dnlib.sln000066400000000000000000000047511325033663500152020ustar00rootroot00000000000000 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}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "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 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal dnlib-2.1_VS2010/dnlib.snk000066400000000000000000000011241325033663500151700ustar00rootroot00000000000000$RSA2++Lb*<7wL9z#`B?t'bu>Hs'{,ltmNYkKY(|NUؑڨ GRbh  |2393D*{#W⧤v}*kUnFpCgYEuVx5Z&6J8N@g(DO d3k ˛(8&5S\ G4 ~8ݕݺbz>P~$ޝ! 5fg"M<ߩj3- ^`y8H243pֆl]y1F6 C;9UѬh 4uޱ!ھ"X*\XdX*ѓCjBYb!Vd/ceBrj(;9fY?꛴ފ.H=EՒM9'_SԷL&Q-QHב{*ؑPT;< 4}e 丒!(w+~oΎQBc%3SP.N‡to@|  @iQl+꾡4b3YEdnlib-2.1_VS2010/src/000077500000000000000000000000001325033663500141545ustar00rootroot00000000000000dnlib-2.1_VS2010/src/DotNet/000077500000000000000000000000001325033663500153515ustar00rootroot00000000000000dnlib-2.1_VS2010/src/DotNet/AllTypesHelper.cs000066400000000000000000000020231325033663500205720ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using dnlib.Threading; namespace dnlib.DotNet { /// /// Returns types without getting stuck in an infinite loop /// public struct AllTypesHelper { /// /// Gets a list of all types and nested types /// /// A list of types public static IEnumerable Types(IEnumerable types) { var visited = new Dictionary(); var stack = new Stack>(); if (types != null) stack.Push(types.GetSafeEnumerable().GetEnumerator()); while (stack.Count > 0) { var enumerator = stack.Pop(); while (enumerator.MoveNext()) { var type = enumerator.Current; if (visited.ContainsKey(type)) continue; visited[type] = true; yield return type; if (type.NestedTypes.Count > 0) { stack.Push(enumerator); enumerator = type.NestedTypes.GetSafeEnumerable().GetEnumerator(); } } } } } } dnlib-2.1_VS2010/src/DotNet/AssemblyAttributes.cs000066400000000000000000000037411325033663500215330ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// Assembly flags from Assembly.Flags column. /// /// See CorHdr.h/CorAssemblyFlags [Flags] public enum AssemblyAttributes : uint { /// No flags set None = 0, /// The assembly ref holds the full (unhashed) public key. PublicKey = 1, /// Processor Architecture unspecified PA_None = 0x0000, /// Processor Architecture: neutral (PE32) PA_MSIL = 0x0010, /// Processor Architecture: x86 (PE32) PA_x86 = 0x0020, /// Processor Architecture: Itanium (PE32+) PA_IA64 = 0x0030, /// Processor Architecture: AMD X64 (PE32+) PA_AMD64 = 0x0040, /// Processor Architecture: ARM (PE32) PA_ARM = 0x0050, /// 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 PA_Specified = 0x0080, /// Bits describing the processor architecture PA_Mask = 0x0070, /// Bits describing the PA incl. Specified PA_FullMask = 0x00F0, /// NOT A FLAG, shift count in PA flags <--> index conversion PA_Shift = 0x0004, /// From "DebuggableAttribute". EnableJITcompileTracking = 0x8000, /// From "DebuggableAttribute". DisableJITcompileOptimizer = 0x4000, /// The assembly can be retargeted (at runtime) to an assembly from a different publisher. Retargetable = 0x0100, /// ContentType_Default = 0x0000, /// ContentType_WindowsRuntime = 0x0200, /// Bits describing ContentType ContentType_Mask = 0x0E00, } } dnlib-2.1_VS2010/src/DotNet/AssemblyDef.cs000066400000000000000000001167221325033663500201070ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using System.Reflection; using System.Threading; using dnlib.Utils; using dnlib.DotNet.MD; using dnlib.DotNet.Writer; using dnlib.Threading; using System.Text.RegularExpressions; using dnlib.DotNet.Pdb; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the Assembly table /// 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 uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 14; } } /// public int HasDeclSecurityTag { get { return 2; } } /// /// From column Assembly.HashAlgId /// public AssemblyHashAlgorithm HashAlgorithm { get { return hashAlgorithm; } set { hashAlgorithm = value; } } /// protected AssemblyHashAlgorithm hashAlgorithm; /// /// From columns Assembly.MajorVersion, Assembly.MinorVersion, Assembly.BuildNumber, /// Assembly.RevisionNumber. /// /// If is null public Version Version { get { return version; } set { if (value == null) throw new ArgumentNullException("value"); version = value; } } /// protected Version version; /// /// From column Assembly.Flags /// public AssemblyAttributes Attributes { get { return (AssemblyAttributes)attributes; } set { attributes = (int)value; } } /// Attributes protected int attributes; /// /// From column Assembly.PublicKey /// /// An empty is created if the caller writes null public PublicKey PublicKey { get { return publicKey; } set { publicKey = value ?? new PublicKey(); } } /// protected PublicKey publicKey; /// /// Gets the public key token which is calculated from /// public PublicKeyToken PublicKeyToken { get { return publicKey.Token; } } /// /// From column Assembly.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// From column Assembly.Locale /// public UTF8String Culture { get { return culture; } set { culture = value; } } /// Name protected UTF8String culture; /// public ThreadSafe.IList DeclSecurities { get { if (declSecurities == null) InitializeDeclSecurities(); return declSecurities; } } /// protected ThreadSafe.IList declSecurities; /// Initializes protected virtual void InitializeDeclSecurities() { Interlocked.CompareExchange(ref declSecurities, ThreadSafeListCreator.Create(), null); } /// public PublicKeyBase PublicKeyOrToken { get { return publicKey; } } /// public string FullName { get { return GetFullNameWithPublicKeyToken(); } } /// public string FullNameToken { get { return GetFullNameWithPublicKeyToken(); } } /// /// Gets all modules. The first module is always the . /// public ThreadSafe.IList Modules { get { if (modules == null) InitializeModules(); return modules; } } /// protected LazyList modules; /// Initializes protected virtual void InitializeModules() { Interlocked.CompareExchange(ref modules, new LazyList(this), null); } /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 14; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// public bool HasDeclSecurities { get { return DeclSecurities.Count > 0; } } /// /// true if is not empty /// public bool HasModules { get { return 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); } } /// /// Modify property: = /// ( & ) | . /// /// 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 attributes = (attributes & (int)andMask) | (int)orMask; #endif } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// 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); } } /// /// Gets/sets the processor architecture /// public AssemblyAttributes ProcessorArchitecture { get { return (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); } } /// /// true if unspecified processor architecture /// public bool IsProcessorArchitectureNone { get { return ((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; } } /// /// true if x86 (PE32) architecture /// public bool IsProcessorArchitectureX86 { get { return ((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; } } /// /// true if x64 (PE32+) architecture /// public bool IsProcessorArchitectureX64 { get { return ((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; } } /// /// true if eg. reference assembly (not runnable) /// public bool IsProcessorArchitectureNoPlatform { get { return ((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); } } /// /// Gets/sets the bit /// public bool EnableJITcompileTracking { get { return ((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); } } /// /// Gets/sets the bit /// public bool IsRetargetable { get { return ((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); } } /// /// true if content type is Default /// public bool IsContentTypeDefault { get { return ((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; } } /// /// Finds a module in this assembly /// /// 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) continue; if (UTF8String.CaseInsensitiveEquals(module.Name, name)) return module; } return null; } /// /// Creates an instance from a file /// /// File name of an existing .NET assembly /// Module context or null /// 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)); } /// /// Creates an instance from a file /// /// File name of an existing .NET assembly /// Module creation options or null /// 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 = null) { if (fileName == null) throw new ArgumentNullException("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)); return asm; } catch { if (module != null) module.Dispose(); throw; } } /// /// Creates an instance from a byte[] /// /// Contents of a .NET assembly /// Module context or null /// 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)); } /// /// Creates an instance from a byte[] /// /// Contents of a .NET assembly /// Module creation options or null /// 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 = null) { if (data == null) throw new ArgumentNullException("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())); return asm; } catch { if (module != null) module.Dispose(); throw; } } /// /// Creates an instance from a memory location /// /// Address of a .NET assembly /// Module context or null /// 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)); } /// /// Creates an instance from a memory location /// /// Address of a .NET assembly /// Module creation options or null /// 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 = null) { if (addr == IntPtr.Zero) throw new ArgumentNullException("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())); return asm; } catch { if (module != 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 /// Module context or null /// 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)); } /// /// 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 /// Module creation options or null /// 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 = null) { if (stream == null) throw new ArgumentNullException("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())); return asm; } catch { if (module != null) module.Dispose(); throw; } } /// /// Gets the assembly name with the public key /// public string GetFullNameWithPublicKey() { return GetFullName(publicKey); } /// /// 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); } /// /// Finds a . For speed, enable /// if possible (read the documentation first). /// /// Full name of the type (no assembly information) /// true if it's a reflection name, and nested /// type names are separated by a + character. If false, nested type names /// 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) continue; var type = module.Find(fullName, isReflectionName); if (type != null) return type; } return null; } /// /// Finds a . Its scope (i.e., module or assembly) is ignored when /// looking up the type. For speed, enable /// if possible (read the documentation first). /// /// 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) continue; var type = module.Find(typeRef); if (type != null) return type; } return 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 = null) { ManifestModule.Write(filename, options); } /// /// Writes the assembly to a stream. /// /// Destination stream /// Writer 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) return false; if (this == targetAsm) return true; // Both must be unsigned or both must be signed according to the // InternalsVisibleToAttribute documentation. if (PublicKeyBase.IsNullOrEmpty2(publicKey) != PublicKeyBase.IsNullOrEmpty2(targetAsm.PublicKey)) return false; 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)); if (arg.Type.GetElementType() != ElementType.String) continue; var asmName = arg.Value as UTF8String; if (UTF8String.IsNull(asmName)) continue; var asmInfo = new AssemblyNameInfo(asmName); if (asmInfo.Name != name) continue; if (!PublicKeyBase.IsNullOrEmpty2(publicKey)) { if (!PublicKey.Equals(asmInfo.PublicKeyOrToken as PublicKey)) continue; } else if (!PublicKeyBase.IsNullOrEmpty2(asmInfo.PublicKeyOrToken)) continue; return true; } return false; } /// /// Adds or updates an existing System.Reflection.AssemblySignatureKeyAttribute /// attribute. This attribute is used in enhanced strong naming with key migration. /// See http://msdn.microsoft.com/en-us/library/hh415055.aspx /// /// Identity public key /// Identity strong name key pair /// Signature public key public void UpdateOrCreateAssemblySignatureKeyAttribute(StrongNamePublicKey identityPubKey, StrongNameKey identityKey, StrongNamePublicKey signaturePubKey) { var manifestModule = ManifestModule; if (manifestModule == 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; }); if (IsValidAssemblySignatureKeyAttribute(ca)) ca.NamedArguments.Clear(); else ca = CreateAssemblySignatureKeyAttribute(); var counterSig = StrongNameKey.CreateCounterSignatureAsString(identityPubKey, identityKey, signaturePubKey); ca.ConstructorArguments[0] = new CAArgument(manifestModule.CorLibTypes.String, new UTF8String(signaturePubKey.ToString())); ca.ConstructorArguments[1] = new CAArgument(manifestModule.CorLibTypes.String, new UTF8String(counterSig)); CustomAttributes.Add(ca); } bool IsValidAssemblySignatureKeyAttribute(CustomAttribute ca) { #if THREAD_SAFE return false; #else if (ca == null) return false; var ctor = ca.Constructor; if (ctor == null) return false; var sig = ctor.MethodSig; if (sig == null || sig.Params.Count != 2) return false; if (sig.Params[0].GetElementType() != ElementType.String) return false; if (sig.Params[1].GetElementType() != ElementType.String) return false; if (ca.ConstructorArguments.Count != 2) return false; return true; #endif } CustomAttribute CreateAssemblySignatureKeyAttribute() { var manifestModule = ManifestModule; var owner = manifestModule.UpdateRowId(new TypeRefUser(manifestModule, "System.Reflection", "AssemblySignatureKeyAttribute", manifestModule.CorLibTypes.AssemblyRef)); var methodSig = MethodSig.CreateInstance(manifestModule.CorLibTypes.Void, manifestModule.CorLibTypes.String, manifestModule.CorLibTypes.String); var ctor = manifestModule.UpdateRowId(new MemberRefUser(manifestModule, MethodDef.InstanceConstructorName, methodSig, owner)); var ca = new CustomAttribute(ctor); ca.ConstructorArguments.Add(new CAArgument(manifestModule.CorLibTypes.String, UTF8String.Empty)); ca.ConstructorArguments.Add(new CAArgument(manifestModule.CorLibTypes.String, UTF8String.Empty)); 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) return; #if DEBUG if (module.Assembly == null) throw new InvalidOperationException("Module.Assembly == null"); #endif } /// void IListListener.OnAdd(int index, ModuleDef module) { if (module == null) return; if (module.Assembly != 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) module.Assembly = null; } /// void IListListener.OnResize(int index) { } /// void IListListener.OnClear() { foreach (var module in Modules.GetEnumerable_NoLock()) { if (module != null) module.Assembly = null; } } /// public override string ToString() { return FullName; } } /// /// An Assembly row created by the user and not present in the original .NET file /// public class AssemblyDefUser : AssemblyDef { /// /// Default constructor /// public AssemblyDefUser() : this(UTF8String.Empty, new Version(0, 0, 0, 0)) { } /// /// Constructor /// /// Simple name /// If any of the args is invalid public AssemblyDefUser(UTF8String name) : this(name, new Version(0, 0, 0, 0), new PublicKey()) { } /// /// Constructor /// /// Simple name /// Version /// If any of the args is invalid public AssemblyDefUser(UTF8String name, Version version) : this(name, version, new PublicKey()) { } /// /// Constructor /// /// Simple name /// Version /// Public key /// If any of the args is invalid public AssemblyDefUser(UTF8String name, Version version, PublicKey publicKey) : this(name, version, publicKey, UTF8String.Empty) { } /// /// Constructor /// /// Simple name /// Version /// Public key /// 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); this.name = name; this.version = version; this.publicKey = publicKey ?? new PublicKey(); this.culture = locale; this.attributes = (int)AssemblyAttributes.None; } /// /// Constructor /// /// Assembly name info /// If is null public AssemblyDefUser(AssemblyName asmName) : this(new AssemblyNameInfo(asmName)) { this.hashAlgorithm = (AssemblyHashAlgorithm)asmName.HashAlgorithm; this.attributes = (int)asmName.Flags; } /// /// Constructor /// /// 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; } } /// /// Created from a row in the Assembly table /// sealed class AssemblyDefMD : AssemblyDef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; /// public uint OrigRid { get { return 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])); 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) => { ModuleDef module; if (index == 0) module = readerModule; else module = readerModule.ReadModule(((RidList)list2)[index - 1], this); if (module == null) module = new ModuleDefUser("INVALID", Guid.NewGuid()); module.Assembly = this; return module; }); Interlocked.CompareExchange(ref modules, tmp, null); } /// 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])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); 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]; var caRow = readerModule.TablesStream.ReadCustomAttributeRow(caRid); if (caRow == null) continue; var caType = readerModule.ResolveCustomAttributeType(caRow.Type, gpContext); UTF8String ns, name; if (!TryGetName(caType, out ns, out name)) continue; if (ns != nameSystemRuntimeVersioning || name != nameTargetFrameworkAttribute) continue; var ca = CustomAttributeReader.Read(readerModule, caType, caRow.Value, gpContext); if (ca == null || ca.ConstructorArguments.Count != 1) continue; var s = ca.ConstructorArguments[0].Value as UTF8String; if ((object)s == null) continue; string tmpFramework, tmpProfile; Version tmpVersion; if (TryCreateTargetFrameworkInfo(s, out tmpFramework, out tmpVersion, out 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; var mr = caType as MemberRef; if (mr != null) type = mr.DeclaringType; else { var md = caType as MethodDef; type = md == null ? null : md.DeclaringType; } var tr = type as TypeRef; if (tr != null) { ns = tr.Namespace; name = tr.Name; return true; } var td = type as TypeDef; if (td != null) { 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 == null) return false; framework = frameworkRes; version = versionRes; profile = profileRes; return true; } static int ParseInt32(string s) { int res; return int.TryParse(s, out 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 /// /// The module which contains this Assembly row /// Row ID /// If is null /// If is invalid public AssemblyDefMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.AssemblyTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("Assembly rid {0} does not exist", rid)); #endif this.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)); } } } dnlib-2.1_VS2010/src/DotNet/AssemblyHash.cs000066400000000000000000000100361325033663500202630ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using System.Security.Cryptography; namespace dnlib.DotNet { /// /// Hashes some data according to a /// struct AssemblyHash : IDisposable { readonly HashAlgorithm hasher; /// /// Constructor /// /// 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 void Dispose() { if (hasher != null) ((IDisposable)hasher).Dispose(); } /// /// Hash data /// /// If is an unsupported hash algorithm, then /// will be used as the hash algorithm. /// The data /// The algorithm to use /// Hashed data or null if was null public static byte[] Hash(byte[] data, AssemblyHashAlgorithm hashAlgo) { if (data == null) return null; using (var asmHash = new AssemblyHash(hashAlgo)) { asmHash.Hash(data); return asmHash.ComputeHash(); } } /// /// Hash data /// /// Data public void Hash(byte[] data) { Hash(data, 0, data.Length); } /// /// Hash data /// /// Data /// Offset /// Length public void Hash(byte[] data, int offset, int length) { if (hasher.TransformBlock(data, offset, length, data, offset) != length) throw new IOException("Could not calculate hash"); } /// /// Hash stream data /// /// Stream /// Number of bytes to hash /// Temp buffer public void Hash(Stream stream, uint length, byte[] buffer) { while (length > 0) { int len = length > (uint)buffer.Length ? buffer.Length : (int)length; if (stream.Read(buffer, 0, len) != len) throw new IOException("Could not read data"); Hash(buffer, 0, len); length -= (uint)len; } } /// /// Computes the hash /// public byte[] ComputeHash() { hasher.TransformFinalBlock(new byte[0], 0, 0); return hasher.Hash; } /// /// Creates a public key token from the hash of some /// /// A public key is hashed, and the last 8 bytes of the hash, in reverse /// order, is used as the public key token /// The data /// A new instance public static PublicKeyToken CreatePublicKeyToken(byte[] publicKeyData) { if (publicKeyData == null) return new PublicKeyToken(); var hash = Hash(publicKeyData, AssemblyHashAlgorithm.SHA1); byte[] 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); } } } dnlib-2.1_VS2010/src/DotNet/AssemblyHashAlgorithm.cs000066400000000000000000000031501325033663500221310ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Any ALG_CLASS_HASH type in WinCrypt.h can be used by Microsoft's CLI implementation /// public enum AssemblyHashAlgorithm : uint { /// None = 0, /// MD2 = 0x8001, /// MD4 = 0x8002, /// This is a reserved value in the CLI MD5 = 0x8003, /// The only algorithm supported by the CLI SHA1 = 0x8004, /// MAC = 0x8005, /// SSL3_SHAMD5 = 0x8008, /// HMAC = 0x8009, /// TLS1PRF = 0x800A, /// HASH_REPLACE_OWF = 0x800B, /// SHA_256 = 0x800C, /// SHA_384 = 0x800D, /// SHA_512 = 0x800E, } 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; } } } } dnlib-2.1_VS2010/src/DotNet/AssemblyNameComparer.cs000066400000000000000000000177171325033663500217660ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; namespace dnlib.DotNet { /// /// Flags used by /// [Flags] public enum AssemblyNameComparerFlags { /// /// Compare assembly simple name /// Name = 1, /// /// Compare assembly version /// Version = 2, /// /// Compare assembly public key token /// PublicKeyToken = 4, /// /// Compare assembly culture /// Culture = 8, /// /// Compare content type /// ContentType = 0x10, /// /// Compare assembly simple name, version, public key token, locale and content type /// All = Name | Version | PublicKeyToken | Culture | ContentType, } /// /// Compares two assembly names /// public struct AssemblyNameComparer : IEqualityComparer { /// /// Compares the name, version, public key token, culture and content type /// public static 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); /// /// Compares only the name /// public static AssemblyNameComparer NameOnly = new AssemblyNameComparer(AssemblyNameComparerFlags.Name); readonly AssemblyNameComparerFlags flags; /// /// Gets the bit /// public bool CompareName { get { return (flags & AssemblyNameComparerFlags.Name) != 0; } } /// /// Gets the bit /// public bool CompareVersion { get { return (flags & AssemblyNameComparerFlags.Version) != 0; } } /// /// Gets the bit /// public bool ComparePublicKeyToken { get { return (flags & AssemblyNameComparerFlags.PublicKeyToken) != 0; } } /// /// Gets the bit /// public bool CompareCulture { get { return (flags & AssemblyNameComparerFlags.Culture) != 0; } } /// /// Gets the bit /// public bool CompareContentType { get { return (flags & AssemblyNameComparerFlags.ContentType) != 0; } } /// /// Constructor /// /// Comparison flags public AssemblyNameComparer(AssemblyNameComparerFlags flags) { this.flags = flags; } /// /// Compares two assembly names /// /// First /// Second /// < 0 if a < b, 0 if a == b, > 0 if a > b public int CompareTo(IAssembly a, IAssembly b) { if (a == b) return 0; if (a == null) return -1; if (b == null) return 1; int v; if (CompareName && (v = UTF8String.CaseInsensitiveCompareTo(a.Name, b.Name)) != 0) return v; if (CompareVersion && (v = Utils.CompareTo(a.Version, b.Version)) != 0) return v; if (ComparePublicKeyToken && (v = PublicKeyBase.TokenCompareTo(a.PublicKeyOrToken, b.PublicKeyOrToken)) != 0) return v; if (CompareCulture && (v = Utils.LocaleCompareTo(a.Culture, b.Culture)) != 0) return v; if (CompareContentType && (v = a.ContentType.CompareTo(b.ContentType)) != 0) return v; return 0; } /// /// Compares two assembly names /// /// First /// Second /// true if equal, false otherwise public bool Equals(IAssembly a, IAssembly b) { return CompareTo(a, b) == 0; } /// /// Figures out which of two assembly names is closer to another assembly name /// /// Requested assembly name /// First /// Second /// -1 if both are equally close, 0 if is closest, 1 if /// is closest public int CompareClosest(IAssembly requested, IAssembly a, IAssembly b) { if (a == b) return 0; if (a == null) return !CompareName ? 1 : UTF8String.CaseInsensitiveEquals(requested.Name, b.Name) ? 1 : 0; if (b == null) return !CompareName ? 0 : UTF8String.CaseInsensitiveEquals(requested.Name, a.Name) ? 0 : 1; // Compare the most important parts first: // 1. Assembly simple name // 2. Public key token // 3. Version // 4. Locale // 5. Content type if (CompareName) { // If the name only matches one of a or b, return that one. bool na = UTF8String.CaseInsensitiveEquals(requested.Name, a.Name); bool nb = UTF8String.CaseInsensitiveEquals(requested.Name, b.Name); if (na && !nb) return 0; if (!na && nb) return 1; if (!na && !nb) return -1; } if (ComparePublicKeyToken) { bool pa, pb; if (PublicKeyBase.IsNullOrEmpty2(requested.PublicKeyOrToken)) { // If one of them has a pkt but the other one hasn't, return the one with // no pkt. pa = PublicKeyBase.IsNullOrEmpty2(a.PublicKeyOrToken); pb = PublicKeyBase.IsNullOrEmpty2(b.PublicKeyOrToken); } else { // If one of them has the correct pkt, but the other one has an incorrect // pkt, return the one with the correct pkt. pa = PublicKeyBase.TokenEquals(requested.PublicKeyOrToken, a.PublicKeyOrToken); pb = PublicKeyBase.TokenEquals(requested.PublicKeyOrToken, b.PublicKeyOrToken); } if (pa && !pb) return 0; if (!pa && pb) return 1; } if (CompareVersion && !Utils.Equals(a.Version, b.Version)) { var rv = Utils.CreateVersionWithNoUndefinedValues(requested.Version); if (rv == new Version(0, 0, 0, 0)) rv = new Version(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue); int va = Utils.CompareTo(a.Version, rv); int vb = Utils.CompareTo(b.Version, rv); if (va == 0) return 0; // vb != 0 so return 0 if (vb == 0) return 1; // va != 0 so return 1 if (va > 0 && vb < 0) return 0; if (va < 0 && vb > 0) return 1; // Now either both a and b's version > req version or both are < req version if (va > 0) { // a.Version and b.Version > req.Version. Pick the one that is closest. return Utils.CompareTo(a.Version, b.Version) < 0 ? 0 : 1; } else { // a.Version and b.Version < req.Version. Pick the one that is closest. return Utils.CompareTo(a.Version, b.Version) > 0 ? 0 : 1; } } if (CompareCulture) { bool la = Utils.LocaleEquals(requested.Culture, a.Culture); bool lb = Utils.LocaleEquals(requested.Culture, b.Culture); if (la && !lb) return 0; if (!la && lb) return 1; } if (CompareContentType) { bool ca = requested.ContentType == a.ContentType; bool cb = requested.ContentType == b.ContentType; if (ca && !cb) return 0; if (!ca && cb) return 1; } return -1; } /// /// Gets the hash code of an assembly name /// /// Assembly name /// The hash code public int GetHashCode(IAssembly a) { if (a == null) return 0; int hash = 0; if (CompareName) hash += UTF8String.GetHashCode(a.Name); if (CompareVersion) hash += Utils.CreateVersionWithNoUndefinedValues(a.Version).GetHashCode(); if (ComparePublicKeyToken) hash += PublicKeyBase.GetHashCodeToken(a.PublicKeyOrToken); if (CompareCulture) hash += Utils.GetHashCodeLocale(a.Culture); if (CompareContentType) hash += (int)a.ContentType; return hash; } } } dnlib-2.1_VS2010/src/DotNet/AssemblyNameInfo.cs000066400000000000000000000213361325033663500211010ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Reflection; namespace dnlib.DotNet { /// /// Stores assembly name information /// public sealed class AssemblyNameInfo : IAssembly { AssemblyHashAlgorithm hashAlgId; Version version; AssemblyAttributes flags; PublicKeyBase publicKeyOrToken; UTF8String name; UTF8String culture; /// /// Gets/sets the /// public AssemblyHashAlgorithm HashAlgId { get { return hashAlgId; } set { hashAlgId = value; } } /// /// Gets/sets the or null if none specified /// public Version Version { get { return version; } set { version = value; } } /// /// Gets/sets the /// public AssemblyAttributes Attributes { get { return flags; } set { flags = value; } } /// /// Gets/sets the public key or token /// public PublicKeyBase PublicKeyOrToken { get { return 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 /// public UTF8String Culture { get { return culture; } set { culture = value; } } /// /// Gets the full name of the assembly /// public string FullName { get { return 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); } } /// /// Modify property: = /// ( & ) | . /// /// Value to AND /// Value to OR void ModifyAttributes(AssemblyAttributes andMask, AssemblyAttributes orMask) { Attributes = (Attributes & andMask) | orMask; } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyAttributes(bool set, AssemblyAttributes flags) { if (set) Attributes |= flags; else Attributes &= ~flags; } /// /// Gets/sets the bit /// public bool HasPublicKey { get { return (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); } } /// /// Gets/sets the processor architecture /// public AssemblyAttributes ProcessorArchitectureFull { get { return 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; } } /// /// true if neutral (PE32) architecture /// public bool IsProcessorArchitectureMSIL { get { return (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_MSIL; } } /// /// true if x86 (PE32) architecture /// public bool IsProcessorArchitectureX86 { get { return (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; } } /// /// true if x64 (PE32+) architecture /// public bool IsProcessorArchitectureX64 { get { return (Attributes & AssemblyAttributes.PA_Mask) == AssemblyAttributes.PA_AMD64; } } /// /// true if ARM (PE32) architecture /// public bool IsProcessorArchitectureARM { get { return (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; } } /// /// Gets/sets the bit /// public bool IsProcessorArchitectureSpecified { get { return (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); } } /// /// Gets/sets the bit /// public bool DisableJITcompileOptimizer { get { return (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); } } /// /// Gets/sets the content type /// public AssemblyAttributes ContentType { get { return 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; } } /// /// true if content type is WindowsRuntime /// public bool IsContentTypeWindowsRuntime { get { return (Attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_WindowsRuntime; } } /// /// Default constructor /// public AssemblyNameInfo() { } /// /// Constructor /// /// An assembly name public AssemblyNameInfo(string asmFullName) : this(ReflectionTypeNameParser.ParseAssemblyRef(asmFullName)) { } /// /// Constructor /// /// The assembly public AssemblyNameInfo(IAssembly asm) { if (asm == 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; } /// /// Constructor /// /// Assembly name info public AssemblyNameInfo(AssemblyName asmName) { if (asmName == 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()) ?? PublicKeyBase.CreatePublicKeyToken(asmName.GetPublicKeyToken()); this.name = asmName.Name ?? string.Empty; this.culture = asmName.CultureInfo != null && asmName.CultureInfo.Name != null ? asmName.CultureInfo.Name : string.Empty; } /// public override string ToString() { return FullName; } } } dnlib-2.1_VS2010/src/DotNet/AssemblyRef.cs000066400000000000000000000440041325033663500201160ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Reflection; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the AssemblyRef table /// 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 /// when it references a type in the current assembly). /// public static readonly AssemblyRef CurrentAssembly = new AssemblyRefUser("<<>>"); /// /// The row id in its table /// protected uint rid; /// public MDToken MDToken { get { return new MDToken(Table.AssemblyRef, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 15; } } /// public int ImplementationTag { get { return 1; } } /// public int ResolutionScopeTag { get { return 2; } } /// public ScopeType ScopeType { get { return ScopeType.AssemblyRef; } } /// public string ScopeName { get { return FullName; } } /// /// From columns AssemblyRef.MajorVersion, AssemblyRef.MinorVersion, /// AssemblyRef.BuildNumber, AssemblyRef.RevisionNumber /// /// If is null public Version Version { get { return version; } set { if (value == null) throw new ArgumentNullException("value"); version = value; } } /// protected Version version; /// /// From column AssemblyRef.Flags /// public AssemblyAttributes Attributes { get { return (AssemblyAttributes)attributes; } set { attributes = (int)value; } } /// Attributes protected int attributes; /// /// From column AssemblyRef.PublicKeyOrToken /// /// If is null public PublicKeyBase PublicKeyOrToken { get { return publicKeyOrToken; } set { if (value == null) throw new ArgumentNullException("value"); publicKeyOrToken = value; } } /// protected PublicKeyBase publicKeyOrToken; /// /// From column AssemblyRef.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// From column AssemblyRef.Locale /// public UTF8String Culture { get { return culture; } set { culture = value; } } /// Culture protected UTF8String culture; /// /// From column AssemblyRef.HashValue /// public byte[] Hash { get { return hashValue; } set { hashValue = value; } } /// protected byte[] hashValue; /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 15; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// public string FullName { get { return FullNameToken; } } /// /// Same as , except that it uses the PublicKey if available. /// public string RealFullName { get { return Utils.GetAssemblyNameString(name, version, culture, publicKeyOrToken, Attributes); } } /// /// 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); } } /// /// Modify property: = /// ( & ) | . /// /// 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 attributes = (attributes & (int)andMask) | (int)orMask; #endif } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// 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); } } /// /// Gets/sets the processor architecture /// public AssemblyAttributes ProcessorArchitecture { get { return (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); } } /// /// true if unspecified processor architecture /// public bool IsProcessorArchitectureNone { get { return ((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; } } /// /// true if x86 (PE32) architecture /// public bool IsProcessorArchitectureX86 { get { return ((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; } } /// /// true if x64 (PE32+) architecture /// public bool IsProcessorArchitectureX64 { get { return ((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; } } /// /// true if eg. reference assembly (not runnable) /// public bool IsProcessorArchitectureNoPlatform { get { return ((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); } } /// /// Gets/sets the bit /// public bool EnableJITcompileTracking { get { return ((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); } } /// /// Gets/sets the bit /// public bool IsRetargetable { get { return ((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); } } /// /// true if content type is Default /// public bool IsContentTypeDefault { get { return ((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 override string ToString() { return FullName; } } /// /// An AssemblyRef row created by the user and not present in the original .NET file /// 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")); } /// /// 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")); } /// /// 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")); } /// /// 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")); } /// /// Default constructor /// public AssemblyRefUser() : this(UTF8String.Empty) { } /// /// Constructor /// /// Simple name /// If any of the args is invalid public AssemblyRefUser(UTF8String name) : this(name, new Version(0, 0, 0, 0)) { } /// /// Constructor /// /// Simple name /// Version /// If any of the args is invalid public AssemblyRefUser(UTF8String name, Version version) : this(name, version, new PublicKey()) { } /// /// Constructor /// /// Simple name /// Version /// Public key or public key token /// If any of the args is invalid public AssemblyRefUser(UTF8String name, Version version, PublicKeyBase publicKey) : this(name, version, publicKey, UTF8String.Empty) { } /// /// Constructor /// /// Simple name /// Version /// Public key or public key token /// 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"); this.name = name; this.version = version; this.publicKeyOrToken = publicKey; this.culture = locale; this.attributes = (int)(publicKey is PublicKey ? AssemblyAttributes.PublicKey : AssemblyAttributes.None); } /// /// Constructor /// /// Assembly name info /// If is null public AssemblyRefUser(AssemblyName asmName) : this(new AssemblyNameInfo(asmName)) { this.attributes = (int)asmName.Flags; } /// /// Constructor /// /// Assembly public AssemblyRefUser(IAssembly assembly) { if (assembly == 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); } } /// /// Created from a row in the AssemblyRef table /// sealed class AssemblyRefMD : AssemblyRef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; /// public uint OrigRid { get { return 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])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this AssemblyRef row /// Row ID /// If is null /// If is invalid public AssemblyRefMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.AssemblyRefTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("AssemblyRef rid {0} does not exist", rid)); #endif this.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); else this.publicKeyOrToken = new PublicKeyToken(pkData); this.name = readerModule.StringsStream.ReadNoNull(name); this.culture = readerModule.StringsStream.ReadNoNull(culture); this.hashValue = readerModule.BlobStream.Read(hashValue); } } } dnlib-2.1_VS2010/src/DotNet/AssemblyResolver.cs000066400000000000000000001062251325033663500212070ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; 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 /// public class AssemblyResolver : IAssemblyResolver { static readonly ModuleDef nullModule = new ModuleDefUser(); // DLL files are searched before EXE files static readonly string[] assemblyExtensions = new string[] { ".dll", ".exe" }; static readonly string[] winMDAssemblyExtensions = new string[] { ".winmd" }; static readonly List gacInfos; static readonly string[] extraMonoPaths; static readonly string[] monoVerDirs = new string[] { // 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(); bool findExactMatch; bool enableFrameworkRedirect; 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 GacInfo(int version, string prefix, string path, IList subDirs) { this.Version = version; this.Prefix = prefix; this.Path = path; this.SubDirs = subDirs; } } static AssemblyResolver() { gacInfos = new List(); if (Type.GetType("Mono.Runtime") != null) { var dirs = new Dictionary(StringComparer.OrdinalIgnoreCase); 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)) continue; dirs[dir] = true; if (Directory.Exists(dir)) { gacInfos.Add(new GacInfo(-1, "", Path.GetDirectoryName(dir), new string[] { Path.GetFileName(dir) })); } dir = Path.GetDirectoryName(dir); foreach (var verDir in monoVerDirs) { var dir2 = dir; foreach (var d in verDir.Split(new char[] { '\\' })) dir2 = Path.Combine(dir2, d); if (Directory.Exists(dir2)) extraMonoPathsList.Add(dir2); } } var paths = Environment.GetEnvironmentVariable("MONO_PATH"); if (paths != null) { foreach (var tmp in paths.Split(Path.PathSeparator)) { var path = tmp.Trim(); if (path != string.Empty && Directory.Exists(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 path = Path.Combine(windir, "assembly"); if (Directory.Exists(path)) { gacInfos.Add(new GacInfo(2, "", path, new string[] { "GAC_32", "GAC_64", "GAC_MSIL", "GAC" })); } // .NET 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[] { "GAC_32", "GAC_64", "GAC_MSIL" })); } } } } static string GetCurrentMonoPrefix() { var path = typeof(object).Module.FullyQualifiedName; for (int i = 0; i < 4; i++) path = Path.GetDirectoryName(path); return path; } static IEnumerable FindMonoPrefixes() { yield return GetCurrentMonoPrefix(); var prefixes = Environment.GetEnvironmentVariable("MONO_GAC_PREFIX"); if (!string.IsNullOrEmpty(prefixes)) { foreach (var tmp in prefixes.Split(Path.PathSeparator)) { var prefix = tmp.Trim(); if (prefix != string.Empty) yield return prefix; } } } /// /// Gets/sets the default /// public ModuleContext DefaultModuleContext { get { return defaultModuleContext; } set { defaultModuleContext = value; } } /// /// true if should find an assembly that matches exactly. /// false if it first tries to match exactly, and if that fails, it picks an /// assembly that is closest to the requested assembly. /// public bool FindExactMatch { get { return 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 /// ignored if is true. /// public bool EnableFrameworkRedirect { get { return enableFrameworkRedirect; } set { enableFrameworkRedirect = value; } } /// /// If true, all modules in newly resolved assemblies will have their /// 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; } } /// /// true to search the Global Assembly Cache. Default value is true. /// public bool UseGAC { get { return useGac; } set { useGac = value; } } /// /// Gets paths searched before trying the standard locations /// public ThreadSafe.IList PreSearchPaths { get { return preSearchPaths; } } /// /// Gets paths searched after trying the standard locations /// public ThreadSafe.IList PostSearchPaths { get { return postSearchPaths; } } /// /// Default constructor /// public AssemblyResolver() : this(null, true) { } /// /// Constructor /// /// Module context for all resolved assemblies public AssemblyResolver(ModuleContext defaultModuleContext) : this(defaultModuleContext, true) { } /// /// 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) { this.defaultModuleContext = defaultModuleContext; this.enableFrameworkRedirect = true; if (addOtherSearchPaths) AddOtherSearchPaths(postSearchPaths); } /// public AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule) { if (assembly == null) return null; if (EnableFrameworkRedirect && !FindExactMatch) FrameworkRedirect.ApplyFrameworkRedirect(ref assembly, sourceModule); #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif AssemblyDef resolvedAssembly = Resolve2(assembly, sourceModule); if (resolvedAssembly == null) { string asmName = UTF8String.ToSystemStringOrEmpty(assembly.Name); string asmNameTrimmed = asmName.Trim(); if (asmName != asmNameTrimmed) { assembly = new AssemblyNameInfo { Name = asmNameTrimmed, Version = assembly.Version, PublicKeyOrToken = assembly.PublicKeyOrToken, Culture = assembly.Culture, }; resolvedAssembly = Resolve2(assembly, sourceModule); } } if (resolvedAssembly == 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; return null; } var key1 = GetAssemblyNameKey(resolvedAssembly); var key2 = GetAssemblyNameKey(assembly); AssemblyDef asm1, asm2; cachedAssemblies.TryGetValue(key1, out asm1); cachedAssemblies.TryGetValue(key2, out asm2); if (asm1 != resolvedAssembly && asm2 != resolvedAssembly) { // This assembly was just resolved if (enableTypeDefCache) { foreach (var module in resolvedAssembly.Modules.GetSafeEnumerable()) { if (module != null) module.EnableTypeDefFindCache = true; } } } bool inserted = false; if (!cachedAssemblies.ContainsKey(key1)) { cachedAssemblies.Add(key1, resolvedAssembly); inserted = true; } if (!cachedAssemblies.ContainsKey(key2)) { cachedAssemblies.Add(key2, resolvedAssembly); inserted = true; } if (inserted || asm1 == resolvedAssembly || asm2 == resolvedAssembly) return resolvedAssembly; // Dupe assembly. Don't insert it. var dupeModule = resolvedAssembly.ManifestModule; if (dupeModule != null) dupeModule.Dispose(); return asm1 ?? asm2; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// public bool AddToCache(AssemblyDef asm) { if (asm == null) return false; var asmKey = GetAssemblyNameKey(asm); AssemblyDef cachedAsm; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (cachedAssemblies.TryGetValue(asmKey, out cachedAsm) && cachedAsm != null) return asm == cachedAsm; cachedAssemblies[asmKey] = asm; return true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// public bool Remove(AssemblyDef asm) { if (asm == null) return false; var asmKey = GetAssemblyNameKey(asm); #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif return cachedAssemblies.Remove(asmKey); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// public void Clear() { List asms; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif asms = new List(cachedAssemblies.Values); cachedAssemblies.Clear(); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif foreach (var asm in asms) { if (asm == null) continue; foreach (var mod in asm.Modules.GetSafeEnumerable()) mod.Dispose(); } } static string GetAssemblyNameKey(IAssembly asmName) { // Make sure the name contains PublicKeyToken= and not PublicKey= return asmName.FullNameToken.ToUpperInvariant(); } AssemblyDef Resolve2(IAssembly assembly, ModuleDef sourceModule) { AssemblyDef resolvedAssembly; if (cachedAssemblies.TryGetValue(GetAssemblyNameKey(assembly), out resolvedAssembly)) return resolvedAssembly; var moduleContext = defaultModuleContext; if (moduleContext == null && sourceModule != 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) return resolvedAssembly; if (!findExactMatch) { resolvedAssembly = FindClosestAssembly(assembly); resolvedAssembly = FindClosestAssembly(assembly, resolvedAssembly, PreFindAssemblies(assembly, sourceModule, false), moduleContext); resolvedAssembly = FindClosestAssembly(assembly, resolvedAssembly, FindAssemblies(assembly, sourceModule, false), moduleContext); resolvedAssembly = FindClosestAssembly(assembly, resolvedAssembly, PostFindAssemblies(assembly, sourceModule, false), moduleContext); } return resolvedAssembly; } /// /// Finds an assembly that exactly matches the requested assembly /// /// Assembly to find /// Search paths or null if none /// Module context /// An instance or null if an exact match /// couldn't be found. AssemblyDef FindExactAssembly(IAssembly assembly, IEnumerable paths, ModuleContext moduleContext) { if (paths == null) return null; var asmComparer = AssemblyNameComparer.CompareAll; foreach (var path in paths.GetSafeEnumerable()) { ModuleDefMD mod = null; try { mod = ModuleDefMD.Load(path, moduleContext); var asm = mod.Assembly; if (asm != null && asmComparer.Equals(assembly, asm)) { mod = null; return asm; } } catch { } finally { if (mod != null) mod.Dispose(); } } return null; } /// /// Finds the closest assembly from the already cached assemblies /// /// Assembly to find /// The closest or null if none found AssemblyDef FindClosestAssembly(IAssembly assembly) { AssemblyDef closest = null; var asmComparer = AssemblyNameComparer.CompareAll; foreach (var asm in cachedAssemblies.Values) { if (asm == null) continue; if (asmComparer.CompareClosest(assembly, closest, asm) == 1) closest = asm; } return closest; } AssemblyDef FindClosestAssembly(IAssembly assembly, AssemblyDef closest, IEnumerable paths, ModuleContext moduleContext) { if (paths == null) return closest; var asmComparer = AssemblyNameComparer.CompareAll; foreach (var path in paths.GetSafeEnumerable()) { 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) { var closeMod = closest.ManifestModule; if (closeMod != null) closeMod.Dispose(); } closest = asm; mod = null; } } catch { } finally { if (mod != null) mod.Dispose(); } } return closest; } /// /// Returns true if is inserted in /// /// Assembly to check bool IsCached(AssemblyDef asm) { if (asm == null) return false; AssemblyDef cachedAsm; return cachedAssemblies.TryGetValue(GetAssemblyNameKey(asm), out cachedAsm) && cachedAsm == asm; } IEnumerable FindAssemblies2(IAssembly assembly, IEnumerable paths) { if (paths != 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); if (File.Exists(fullPath)) yield return fullPath; } } } } /// /// Called before /// /// Assembly to find /// The module that needs to resolve an assembly or null /// We're trying to find an exact match /// null or an enumerable of full paths to try protected virtual IEnumerable PreFindAssemblies(IAssembly assembly, ModuleDef sourceModule, bool matchExactly) { foreach (var path in FindAssemblies2(assembly, preSearchPaths)) yield return path; } /// /// Called after (if it fails) /// /// Assembly to find /// The module that needs to resolve an assembly or null /// We're trying to find an exact match /// null or an enumerable of full paths to try protected virtual IEnumerable PostFindAssemblies(IAssembly assembly, ModuleDef sourceModule, bool matchExactly) { foreach (var path in FindAssemblies2(assembly, postSearchPaths)) yield return path; } /// /// Called after (if it fails) /// /// Assembly to find /// The module that needs to resolve an assembly or null /// We're trying to find an exact match /// 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"); if (File.Exists(path)) yield return path; } else { if (UseGAC) { foreach (var path in FindAssembliesGac(assembly, sourceModule, matchExactly)) yield return path; } } foreach (var path in FindAssembliesModuleSearchPaths(assembly, sourceModule, matchExactly)) yield return path; } IEnumerable FindAssembliesGac(IAssembly assembly, ModuleDef sourceModule, bool matchExactly) { if (matchExactly) return FindAssembliesGacExactly(assembly, sourceModule); return FindAssembliesGacAny(assembly, 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) foreach (var gacInfo in gacInfos) { if (gacInfo.Version == version) yield return gacInfo; } foreach (var gacInfo in gacInfos) { if (gacInfo.Version != version) yield return gacInfo; } } IEnumerable FindAssembliesGacExactly(IAssembly assembly, ModuleDef sourceModule) { foreach (var gacInfo in GetGacInfos(sourceModule)) { foreach (var path in FindAssembliesGacExactly(gacInfo, assembly, sourceModule)) yield return path; } if (extraMonoPaths != null) { foreach (var path in GetExtraMonoPaths(assembly, sourceModule)) yield return path; } } static IEnumerable GetExtraMonoPaths(IAssembly assembly, ModuleDef sourceModule) { if (extraMonoPaths != null) { foreach (var dir in extraMonoPaths) { var file = Path.Combine(dir, assembly.Name + ".dll"); if (File.Exists(file)) yield return file; } } } IEnumerable FindAssembliesGacExactly(GacInfo gacInfo, IAssembly assembly, ModuleDef sourceModule) { var pkt = PublicKeyBase.ToPublicKeyToken(assembly.PublicKeyOrToken); if (gacInfo != null && pkt != 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}_{3}", gacInfo.Prefix, verString, cultureString, pktString)); var pathName = Path.Combine(baseDir, asmSimpleName + ".dll"); if (File.Exists(pathName)) yield return pathName; } } } IEnumerable FindAssembliesGacAny(IAssembly assembly, ModuleDef sourceModule) { foreach (var gacInfo in GetGacInfos(sourceModule)) { foreach (var path in FindAssembliesGacAny(gacInfo, assembly, sourceModule)) yield return path; } if (extraMonoPaths != null) { foreach (var path in GetExtraMonoPaths(assembly, sourceModule)) yield return path; } } IEnumerable FindAssembliesGacAny(GacInfo gacInfo, IAssembly assembly, ModuleDef sourceModule) { if (gacInfo != 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 dir in GetDirs(baseDir)) { var pathName = Path.Combine(dir, asmSimpleName + ".dll"); if (File.Exists(pathName)) yield return pathName; } } } } IEnumerable GetDirs(string baseDir) { if (!Directory.Exists(baseDir)) return emtpyStringArray; var dirs = new List(); try { foreach (var di in new DirectoryInfo(baseDir).GetDirectories()) dirs.Add(di.FullName); } catch { } return dirs; } static readonly string[] emtpyStringArray = new string[0]; IEnumerable FindAssembliesModuleSearchPaths(IAssembly assembly, ModuleDef sourceModule, bool matchExactly) { string asmSimpleName = UTF8String.ToSystemStringOrEmpty(assembly.Name); var searchPaths = GetSearchPaths(sourceModule); var exts = assembly.IsContentTypeWindowsRuntime ? winMDAssemblyExtensions : assemblyExtensions; foreach (var ext in exts) { foreach (var path in searchPaths.GetSafeEnumerable()) { 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); if (File.Exists(path2)) yield return path2; } } } } /// /// Gets all search paths to use for this module /// /// 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) keyModule = nullModule; IList searchPaths; if (moduleSearchPaths.TryGetValue(keyModule, out searchPaths)) return searchPaths; moduleSearchPaths[keyModule] = searchPaths = new List(GetModuleSearchPaths(module)); return searchPaths; } /// /// Gets all module search paths. This is usually empty unless its assembly has /// a .config file specifying any additional private search paths in a /// <probing/> element. /// /// The module or null if unknown /// A list of search paths protected virtual IEnumerable GetModuleSearchPaths(ModuleDef module) { return GetModulePrivateSearchPaths(module); } /// /// Gets all private assembly search paths as found in the module's .config file. /// /// The module or null if unknown /// A list of search paths protected IEnumerable GetModulePrivateSearchPaths(ModuleDef module) { if (module == null) return new string[0]; var asm = module.Assembly; if (asm == null) return new string[0]; module = asm.ManifestModule; if (module == null) return new string[0]; // 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); } } catch { } if (baseDir != null) return new List { baseDir }; return new string[0]; } IEnumerable GetPrivatePaths(string baseDir, string configFileName) { var searchPaths = new List(); try { var dirName = Path.GetDirectoryName(Path.GetFullPath(configFileName)); searchPaths.Add(dirName); using (var xmlStream = new FileStream(configFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { var doc = new XmlDocument(); doc.Load(XmlReader.Create(xmlStream)); foreach (var tmp in doc.GetElementsByTagName("probing")) { var probingElem = tmp as XmlElement; if (probingElem == null) continue; var privatePath = probingElem.GetAttribute("privatePath"); if (string.IsNullOrEmpty(privatePath)) continue; foreach (var tmp2 in privatePath.Split(';')) { var path = tmp2.Trim(); if (path == "") continue; var newPath = Path.GetFullPath(Path.Combine(dirName, path.Replace('\\', Path.DirectorySeparatorChar))); if (Directory.Exists(newPath) && newPath.StartsWith(baseDir + Path.DirectorySeparatorChar)) searchPaths.Add(newPath); } } } } catch (ArgumentException) { } catch (IOException) { } catch (XmlException) { } 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.1"); 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\v5.0"); 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\.NETPortable\v5.0"); 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) { if (!Directory.Exists(basePath)) return; 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); } } } dnlib-2.1_VS2010/src/DotNet/CallingConvention.cs000066400000000000000000000022121325033663500213110ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// See CorHdr.h/CorCallingConvention /// [Flags] public enum CallingConvention : byte { /// The managed calling convention Default = 0x0, /// C = 0x1, /// StdCall = 0x2, /// ThisCall = 0x3, /// FastCall = 0x4, /// VarArg = 0x5, /// Field = 0x6, /// LocalSig = 0x7, /// Property = 0x8, /// Unmanaged = 0x9, /// generic method instantiation GenericInst = 0xA, /// used ONLY for 64bit vararg PInvoke calls NativeVarArg = 0xB, /// Calling convention is bottom 4 bits Mask = 0x0F, /// Generic method Generic = 0x10, /// Method needs a 'this' parameter HasThis = 0x20, /// 'this' parameter is the first arg if set (else it's hidden) ExplicitThis = 0x40, /// Used internally by the CLR ReservedByCLR = 0x80, } } dnlib-2.1_VS2010/src/DotNet/CallingConventionSig.cs000066400000000000000000001163541325033663500217710ustar00rootroot00000000000000// 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 /* All signature classes: CallingConventionSig FieldSig MethodBaseSig MethodSig PropertySig LocalSig GenericInstMethodSig */ namespace dnlib.DotNet { /// /// Base class for sigs with a calling convention /// public abstract class CallingConventionSig : IContainsGenericParameter { /// /// The calling convention /// protected CallingConvention callingConvention; byte[] extraData; /// /// Gets/sets the extra data found after the signature /// public byte[] ExtraData { get { return extraData; } set { extraData = value; } } /// /// Returns true if is set /// public bool IsDefault { get { return (callingConvention & CallingConvention.Mask) == CallingConvention.Default; } } /// /// Returns true if is set /// public bool IsC { get { return (callingConvention & CallingConvention.Mask) == CallingConvention.C; } } /// /// Returns true if is set /// public bool IsStdCall { get { return (callingConvention & CallingConvention.Mask) == CallingConvention.StdCall; } } /// /// Returns true if is set /// public bool IsThisCall { get { return (callingConvention & CallingConvention.Mask) == CallingConvention.ThisCall; } } /// /// Returns true if is set /// public bool IsFastCall { get { return (callingConvention & CallingConvention.Mask) == CallingConvention.FastCall; } } /// /// Returns true if is set /// public bool IsVarArg { get { return (callingConvention & CallingConvention.Mask) == CallingConvention.VarArg; } } /// /// Returns true if is set /// public bool IsField { get { return (callingConvention & CallingConvention.Mask) == CallingConvention.Field; } } /// /// Returns true if is set /// public bool IsLocalSig { get { return (callingConvention & CallingConvention.Mask) == CallingConvention.LocalSig; } } /// /// Returns true if is set /// public bool IsProperty { get { return (callingConvention & CallingConvention.Mask) == CallingConvention.Property; } } /// /// Returns true if is set /// public bool IsUnmanaged { get { return (callingConvention & CallingConvention.Mask) == CallingConvention.Unmanaged; } } /// /// Returns true if is set /// public bool IsGenericInst { get { return (callingConvention & CallingConvention.Mask) == CallingConvention.GenericInst; } } /// /// Returns true if is set /// public bool IsNativeVarArg { get { return (callingConvention & CallingConvention.Mask) == CallingConvention.NativeVarArg; } } /// /// Gets/sets the bit /// public bool Generic { get { return (callingConvention & CallingConvention.Generic) != 0; } set { if (value) callingConvention |= CallingConvention.Generic; else callingConvention &= ~CallingConvention.Generic; } } /// /// Gets/sets the bit /// public bool HasThis { get { return (callingConvention & CallingConvention.HasThis) != 0; } set { if (value) callingConvention |= CallingConvention.HasThis; else callingConvention &= ~CallingConvention.HasThis; } } /// /// Gets/sets the bit /// public bool ExplicitThis { get { return (callingConvention & CallingConvention.ExplicitThis) != 0; } set { if (value) callingConvention |= CallingConvention.ExplicitThis; else callingConvention &= ~CallingConvention.ExplicitThis; } } /// /// Gets/sets the bit /// public bool ReservedByCLR { get { return (callingConvention & CallingConvention.ReservedByCLR) != 0; } set { if (value) callingConvention |= CallingConvention.ReservedByCLR; else callingConvention &= ~CallingConvention.ReservedByCLR; } } /// /// true if there's an implicit this parameter /// public bool ImplicitThis { get { return HasThis && !ExplicitThis; } } /// /// true if this contains a /// or a . /// public bool ContainsGenericParameter { get { return TypeHelper.ContainsGenericParameter(this); } } /// /// Default constructor /// protected CallingConventionSig() { } /// /// Constructor /// /// The calling convention protected CallingConventionSig(CallingConvention callingConvention) { this.callingConvention = callingConvention; } /// /// Gets the calling convention /// public CallingConvention GetCallingConvention() { return callingConvention; } } /// /// A field signature /// public sealed class FieldSig : CallingConventionSig { TypeSig type; /// /// Gets/sets the field type /// public TypeSig Type { get { return type; } set { type = value; } } /// /// Default constructor /// public FieldSig() { this.callingConvention = CallingConvention.Field; } /// /// Constructor /// /// Field type public FieldSig(TypeSig type) { this.callingConvention = CallingConvention.Field; this.type = type; } /// /// Constructor /// /// Field type /// The calling convention (must have Field set) internal FieldSig(CallingConvention callingConvention, TypeSig type) { this.callingConvention = callingConvention; this.type = type; } /// /// Clone this /// public FieldSig Clone() { return new FieldSig(callingConvention, type); } /// public override string ToString() { return FullNameCreator.FullName(type == null ? null : type, false, null, null, null, null); } } /// /// Method sig base class /// public abstract class MethodBaseSig : CallingConventionSig { /// protected TypeSig retType; /// protected ThreadSafe.IList parameters; /// protected uint genParamCount; /// protected ThreadSafe.IList paramsAfterSentinel; /// /// Gets/sets the calling convention /// public CallingConvention CallingConvention { get { return callingConvention; } set { callingConvention = value; } } /// /// Gets/sets the return type /// public TypeSig RetType { get { return retType; } set { retType = value; } } /// /// Gets the parameters. This is never null /// public ThreadSafe.IList Params { get { return parameters; } } /// /// Gets/sets the generic param count /// public uint GenParamCount { get { return 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; } } } /// /// A method signature /// public sealed class MethodSig : MethodBaseSig { uint origToken; /// /// Gets/sets the original token. It's set when reading calli instruction operands /// 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; } } /// /// Creates a static MethodSig /// /// Return type public static MethodSig CreateStatic(TypeSig retType) { return 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); } /// /// Creates a static MethodSig /// /// 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); } /// /// Creates a static MethodSig /// /// Return type /// 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); } /// /// 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); } /// /// Creates an instance MethodSig /// /// Return type public static MethodSig CreateInstance(TypeSig retType) { return 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); } /// /// Creates an instance MethodSig /// /// 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); } /// /// Creates an instance MethodSig /// /// Return type /// 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); } /// /// 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); } /// /// 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); } /// /// Creates a static generic MethodSig /// /// 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); } /// /// Creates a static generic MethodSig /// /// Number of generic parameters /// 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); } /// /// Creates a static generic MethodSig /// /// Number of generic parameters /// Return type /// 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); } /// /// Creates a static generic MethodSig /// /// 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); } /// /// 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); } /// /// Creates an instance generic MethodSig /// /// 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); } /// /// Creates an instance generic MethodSig /// /// Number of generic parameters /// 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); } /// /// Creates an instance generic MethodSig /// /// Number of generic parameters /// Return type /// 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); } /// /// Creates an instance generic MethodSig /// /// 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); } /// /// Default constructor /// public MethodSig() { this.parameters = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Calling convention public MethodSig(CallingConvention callingConvention) { this.callingConvention = callingConvention; this.parameters = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Calling convention /// Number of generic parameters public MethodSig(CallingConvention callingConvention, uint genParamCount) { this.callingConvention = callingConvention; this.genParamCount = genParamCount; this.parameters = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Calling convention /// Number of generic parameters /// Return type public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType) { this.callingConvention = callingConvention; this.genParamCount = genParamCount; this.retType = retType; this.parameters = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Calling convention /// Number of generic parameters /// Return type /// Arg type #1 public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, TypeSig argType1) { this.callingConvention = callingConvention; this.genParamCount = genParamCount; this.retType = retType; this.parameters = ThreadSafeListCreator.Create(argType1); } /// /// Constructor /// /// Calling convention /// Number of generic parameters /// Return type /// Arg type #1 /// Arg type #2 public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2) { this.callingConvention = callingConvention; this.genParamCount = genParamCount; this.retType = retType; this.parameters = ThreadSafeListCreator.Create(argType1, argType2); } /// /// Constructor /// /// Calling convention /// Number of generic parameters /// Return type /// Arg type #1 /// Arg type #2 /// Arg type #3 public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, TypeSig argType1, TypeSig argType2, TypeSig argType3) { this.callingConvention = callingConvention; this.genParamCount = genParamCount; this.retType = retType; this.parameters = ThreadSafeListCreator.Create(argType1, argType2, argType3); } /// /// Constructor /// /// Calling convention /// Number of generic parameters /// Return type /// Argument types public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, params TypeSig[] argTypes) { this.callingConvention = callingConvention; this.genParamCount = genParamCount; this.retType = retType; this.parameters = ThreadSafeListCreator.Create(argTypes); } /// /// Constructor /// /// Calling convention /// Number of generic parameters /// Return type /// Argument types public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, IList argTypes) { this.callingConvention = callingConvention; this.genParamCount = genParamCount; this.retType = retType; this.parameters = ThreadSafeListCreator.Create(argTypes); } /// /// Constructor /// /// Calling convention /// Number of generic parameters /// Return type /// Argument types /// Parameters after sentinel public MethodSig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, IList argTypes, IList paramsAfterSentinel) { this.callingConvention = callingConvention; this.genParamCount = genParamCount; this.retType = retType; this.parameters = ThreadSafeListCreator.Create(argTypes); this.paramsAfterSentinel = paramsAfterSentinel == null ? null : ThreadSafeListCreator.Create(paramsAfterSentinel); } /// /// Clone this /// public MethodSig Clone() { return new MethodSig(callingConvention, genParamCount, retType, parameters, paramsAfterSentinel); } /// public override string ToString() { return FullNameCreator.MethodBaseSigFullName(this, null); } } /// /// A property signature /// public sealed class PropertySig : MethodBaseSig { /// /// Creates a static PropertySig /// /// Return type public static PropertySig CreateStatic(TypeSig retType) { return 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); } /// /// Creates a static PropertySig /// /// 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); } /// /// Creates a static PropertySig /// /// Return type /// 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); } /// /// Creates a static PropertySig /// /// Return type /// Argument types public static PropertySig CreateStatic(TypeSig retType, params TypeSig[] argTypes) { return new PropertySig(false, retType, argTypes); } /// /// Creates an instance PropertySig /// /// Return type public static PropertySig CreateInstance(TypeSig retType) { return 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); } /// /// Creates an instance PropertySig /// /// 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); } /// /// Creates an instance PropertySig /// /// Return 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); } /// /// Creates an instance PropertySig /// /// Return type /// Argument types public static PropertySig CreateInstance(TypeSig retType, params TypeSig[] argTypes) { return new PropertySig(true, retType, argTypes); } /// /// Default constructor /// public PropertySig() { this.callingConvention = CallingConvention.Property; this.parameters = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Calling convention (must have Property set) internal PropertySig(CallingConvention callingConvention) { this.callingConvention = callingConvention; this.parameters = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// true if instance, false if static public PropertySig(bool hasThis) { this.callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0); this.parameters = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// true if instance, false if static /// Return type public PropertySig(bool hasThis, TypeSig retType) { this.callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0); this.retType = retType; this.parameters = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// true if instance, false if static /// Return type /// Arg type #1 public PropertySig(bool hasThis, TypeSig retType, TypeSig argType1) { this.callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0); this.retType = retType; this.parameters = ThreadSafeListCreator.Create(argType1); } /// /// Constructor /// /// true if instance, false if static /// Return type /// Arg type #1 /// Arg type #2 public PropertySig(bool hasThis, TypeSig retType, TypeSig argType1, TypeSig argType2) { this.callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0); this.retType = retType; this.parameters = ThreadSafeListCreator.Create(argType1, argType2); } /// /// Constructor /// /// true if instance, false if static /// Return type /// Arg type #1 /// 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); this.retType = retType; this.parameters = ThreadSafeListCreator.Create(argType1, argType2, argType3); } /// /// Constructor /// /// true if instance, false if static /// Return type /// Argument types public PropertySig(bool hasThis, TypeSig retType, params TypeSig[] argTypes) { this.callingConvention = CallingConvention.Property | (hasThis ? CallingConvention.HasThis : 0); this.retType = retType; this.parameters = ThreadSafeListCreator.Create(argTypes); } /// /// Constructor /// /// Calling convention /// Number of generic parameters /// Return type /// Argument types /// Parameters after sentinel internal PropertySig(CallingConvention callingConvention, uint genParamCount, TypeSig retType, IList argTypes, IList paramsAfterSentinel) { this.callingConvention = callingConvention; this.genParamCount = genParamCount; this.retType = retType; this.parameters = ThreadSafeListCreator.Create(argTypes); this.paramsAfterSentinel = paramsAfterSentinel == null ? null : ThreadSafeListCreator.Create(paramsAfterSentinel); } /// /// Clone this /// public PropertySig Clone() { return new PropertySig(callingConvention, genParamCount, retType, parameters, paramsAfterSentinel); } /// public override string ToString() { return FullNameCreator.MethodBaseSigFullName(this, null); } } /// /// A local variables signature /// public sealed class LocalSig : CallingConventionSig { readonly ThreadSafe.IList locals; /// /// All local types. This is never null. /// public ThreadSafe.IList Locals { get { return locals; } } /// /// Default constructor /// public LocalSig() { this.callingConvention = CallingConvention.LocalSig; this.locals = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Calling convention (must have LocalSig set) /// Number of locals internal LocalSig(CallingConvention callingConvention, uint count) { this.callingConvention = callingConvention; this.locals = ThreadSafeListCreator.Create((int)count); } /// /// Constructor /// /// Local type #1 public LocalSig(TypeSig local1) { this.callingConvention = CallingConvention.LocalSig; this.locals = ThreadSafeListCreator.Create(local1); } /// /// Constructor /// /// Local type #1 /// Local type #2 public LocalSig(TypeSig local1, TypeSig local2) { this.callingConvention = CallingConvention.LocalSig; this.locals = ThreadSafeListCreator.Create(local1, local2); } /// /// Constructor /// /// Local type #1 /// 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); } /// /// Constructor /// /// All locals public LocalSig(params TypeSig[] locals) { this.callingConvention = CallingConvention.LocalSig; this.locals = ThreadSafeListCreator.Create(locals); } /// /// Constructor /// /// All locals public LocalSig(IList locals) { this.callingConvention = CallingConvention.LocalSig; this.locals = ThreadSafeListCreator.Create(locals); } /// /// Constructor /// /// All locals (this instance now owns it) /// Dummy internal LocalSig(IList locals, bool dummy) { this.callingConvention = CallingConvention.LocalSig; this.locals = ThreadSafeListCreator.MakeThreadSafe(locals); } /// /// Clone this /// public LocalSig Clone() { return new LocalSig(locals); } } /// /// An instantiated generic method signature /// public sealed class GenericInstMethodSig : CallingConventionSig { readonly ThreadSafe.IList genericArgs; /// /// Gets the generic arguments (must be instantiated types, i.e., closed types) /// public ThreadSafe.IList GenericArguments { get { return genericArgs; } } /// /// Default constructor /// public GenericInstMethodSig() { this.callingConvention = CallingConvention.GenericInst; this.genericArgs = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Calling convention (must have GenericInst set) /// Number of generic args internal GenericInstMethodSig(CallingConvention callingConvention, uint size) { this.callingConvention = callingConvention; this.genericArgs = ThreadSafeListCreator.Create((int)size); } /// /// Constructor /// /// Generic arg #1 public GenericInstMethodSig(TypeSig arg1) { this.callingConvention = CallingConvention.GenericInst; this.genericArgs = ThreadSafeListCreator.Create(arg1); } /// /// Constructor /// /// Generic arg #1 /// Generic arg #2 public GenericInstMethodSig(TypeSig arg1, TypeSig arg2) { this.callingConvention = CallingConvention.GenericInst; this.genericArgs = ThreadSafeListCreator.Create(arg1, arg2); } /// /// Constructor /// /// Generic arg #1 /// 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); } /// /// Constructor /// /// Generic args public GenericInstMethodSig(params TypeSig[] args) { this.callingConvention = CallingConvention.GenericInst; this.genericArgs = ThreadSafeListCreator.Create(args); } /// /// Constructor /// /// Generic args public GenericInstMethodSig(IList args) { this.callingConvention = CallingConvention.GenericInst; this.genericArgs = ThreadSafeListCreator.Create(args); } /// /// Clone this /// public GenericInstMethodSig Clone() { return new GenericInstMethodSig(genericArgs); } } public static partial class Extensions { /// /// Gets the field type /// /// this /// Field type or null if none public static TypeSig GetFieldType(this FieldSig sig) { return sig == null ? null : 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; } /// /// Gets the parameters /// /// this /// The parameters public static IList GetParams(this MethodBaseSig sig) { return sig == null ? ThreadSafeListCreator.Create() : sig.Params; } /// /// Gets the parameter count /// /// this /// Parameter count public static int GetParamCount(this MethodBaseSig sig) { return sig == null ? 0 : sig.Params.Count; } /// /// Gets the generic parameter count /// /// this /// Generic parameter count public static uint GetGenParamCount(this MethodBaseSig sig) { return sig == null ? 0 : sig.GenParamCount; } /// /// 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; } /// /// Gets the locals /// /// this /// All locals public static IList GetLocals(this LocalSig sig) { return sig == null ? ThreadSafeListCreator.Create() : sig.Locals; } /// /// Gets the generic arguments /// /// this /// All generic arguments public static IList GetGenericArguments(this GenericInstMethodSig sig) { return sig == null ? ThreadSafeListCreator.Create() : sig.GenericArguments; } /// /// Gets the property /// /// this /// The type's property or /// false if input isnull public static bool GetIsDefault(this CallingConventionSig sig) { return sig == null ? false : sig.IsDefault; } } } dnlib-2.1_VS2010/src/DotNet/ClassLayout.cs000066400000000000000000000050771325033663500201540ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.DotNet.MD; namespace dnlib.DotNet { /// /// A high-level representation of a row in the ClassLayout table /// public abstract class ClassLayout : IMDTokenProvider { /// /// The row id in its table /// protected uint rid; /// public MDToken MDToken { get { return new MDToken(Table.ClassLayout, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// /// From column ClassLayout.PackingSize /// public ushort PackingSize { get { return packingSize; } set { packingSize = value; } } /// protected ushort packingSize; /// /// From column ClassLayout.ClassSize /// public uint ClassSize { get { return classSize; } set { classSize = value; } } /// protected uint classSize; } /// /// A ClassLayout row created by the user and not present in the original .NET file /// public class ClassLayoutUser : ClassLayout { /// /// Default constructor /// public ClassLayoutUser() { } /// /// Constructor /// /// PackingSize /// ClassSize public ClassLayoutUser(ushort packingSize, uint classSize) { this.packingSize = packingSize; this.classSize = classSize; } } /// /// Created from a row in the ClassLayout table /// sealed class ClassLayoutMD : ClassLayout, IMDTokenProviderMD { readonly uint origRid; /// public uint OrigRid { get { return origRid; } } /// /// Constructor /// /// The module which contains this ClassLayout row /// Row ID /// If is null /// If is invalid public ClassLayoutMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.ClassLayoutTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("ClassLayout rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.classSize = readerModule.TablesStream.ReadClassLayoutRow(origRid, out this.packingSize); } } } dnlib-2.1_VS2010/src/DotNet/Constant.cs000066400000000000000000000125021325033663500174710ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Text; using dnlib.DotNet.MD; namespace dnlib.DotNet { /// /// A high-level representation of a row in the Constant table /// public abstract class Constant : IMDTokenProvider { /// /// The row id in its table /// protected uint rid; /// public MDToken MDToken { get { return new MDToken(Table.Constant, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// /// From column Constant.Type /// public ElementType Type { get { return type; } set { type = value; } } /// protected ElementType type; /// /// From column Constant.Value /// public object Value { get { return value; } set { this.value = value; } } /// protected object value; } /// /// A Constant row created by the user and not present in the original .NET file /// public class ConstantUser : Constant { /// /// Default constructor /// public ConstantUser() { } /// /// Constructor /// /// Value public ConstantUser(object value) { this.type = GetElementType(value); this.value = value; } /// /// Constructor /// /// Value /// Type public ConstantUser(object value, ElementType type) { this.type = type; this.value = value; } static ElementType GetElementType(object value) { if (value == 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; } } } /// /// Created from a row in the Constant table /// sealed class ConstantMD : Constant, IMDTokenProviderMD { readonly uint origRid; /// public uint OrigRid { get { return origRid; } } /// /// Constructor /// /// The module which contains this Constant row /// Row ID /// If is null /// If is invalid public ConstantMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.ConstantTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("Constant rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; uint value = readerModule.TablesStream.ReadConstantRow(origRid, out this.type); this.value = GetValue(this.type, readerModule.BlobStream.ReadNoNull(value)); } static object GetValue(ElementType etype, byte[] data) { switch (etype) { case ElementType.Boolean: if (data == null || data.Length < 1) return false; return BitConverter.ToBoolean(data, 0); case ElementType.Char: if (data == null || data.Length < 2) return (char)0; return BitConverter.ToChar(data, 0); case ElementType.I1: if (data == null || data.Length < 1) return (sbyte)0; return (sbyte)data[0]; case ElementType.U1: if (data == null || data.Length < 1) return (byte)0; return data[0]; case ElementType.I2: if (data == null || data.Length < 2) return (short)0; return BitConverter.ToInt16(data, 0); case ElementType.U2: if (data == null || data.Length < 2) return (ushort)0; return BitConverter.ToUInt16(data, 0); case ElementType.I4: if (data == null || data.Length < 4) return (int)0; return BitConverter.ToInt32(data, 0); case ElementType.U4: if (data == null || data.Length < 4) return (uint)0; return BitConverter.ToUInt32(data, 0); case ElementType.I8: if (data == null || data.Length < 8) return (long)0; return BitConverter.ToInt64(data, 0); case ElementType.U8: if (data == null || data.Length < 8) return (ulong)0; return BitConverter.ToUInt64(data, 0); case ElementType.R4: if (data == null || data.Length < 4) return (float)0; return BitConverter.ToSingle(data, 0); case ElementType.R8: if (data == null || data.Length < 8) return (double)0; return BitConverter.ToDouble(data, 0); case ElementType.String: if (data == null) return string.Empty; return Encoding.Unicode.GetString(data, 0, data.Length / 2 * 2); case ElementType.Class: return null; default: return null; } } } } dnlib-2.1_VS2010/src/DotNet/CorLibTypes.cs000066400000000000000000000124211325033663500200770ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Default implementation of /// public sealed class CorLibTypes : ICorLibTypes { readonly ModuleDef module; CorLibTypeSig typeVoid; CorLibTypeSig typeBoolean; CorLibTypeSig typeChar; CorLibTypeSig typeSByte; CorLibTypeSig typeByte; CorLibTypeSig typeInt16; CorLibTypeSig typeUInt16; CorLibTypeSig typeInt32; CorLibTypeSig typeUInt32; CorLibTypeSig typeInt64; CorLibTypeSig typeUInt64; CorLibTypeSig typeSingle; CorLibTypeSig typeDouble; CorLibTypeSig typeString; CorLibTypeSig typeTypedReference; CorLibTypeSig typeIntPtr; CorLibTypeSig typeUIntPtr; CorLibTypeSig typeObject; readonly AssemblyRef corLibAssemblyRef; /// public CorLibTypeSig Void { get { return typeVoid; } } /// public CorLibTypeSig Boolean { get { return typeBoolean; } } /// public CorLibTypeSig Char { get { return typeChar; } } /// public CorLibTypeSig SByte { get { return typeSByte; } } /// public CorLibTypeSig Byte { get { return typeByte; } } /// public CorLibTypeSig Int16 { get { return typeInt16; } } /// public CorLibTypeSig UInt16 { get { return typeUInt16; } } /// public CorLibTypeSig Int32 { get { return typeInt32; } } /// public CorLibTypeSig UInt32 { get { return typeUInt32; } } /// public CorLibTypeSig Int64 { get { return typeInt64; } } /// public CorLibTypeSig UInt64 { get { return typeUInt64; } } /// public CorLibTypeSig Single { get { return typeSingle; } } /// public CorLibTypeSig Double { get { return typeDouble; } } /// public CorLibTypeSig String { get { return typeString; } } /// public CorLibTypeSig TypedReference { get { return typeTypedReference; } } /// public CorLibTypeSig IntPtr { get { return typeIntPtr; } } /// public CorLibTypeSig UIntPtr { get { return typeUIntPtr; } } /// public CorLibTypeSig Object { get { return typeObject; } } /// public AssemblyRef AssemblyRef { get { return corLibAssemblyRef; } } /// /// Constructor /// /// The owner module public CorLibTypes(ModuleDef module) : this(module, null) { } /// /// Constructor /// /// The owner module /// Corlib assembly reference or null if a default /// assembly reference should be created public CorLibTypes(ModuleDef module, AssemblyRef corLibAssemblyRef) { this.module = module; this.corLibAssemblyRef = corLibAssemblyRef ?? CreateCorLibAssemblyRef(); Initialize(); } AssemblyRef CreateCorLibAssemblyRef() { return module.UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR20()); } void Initialize() { bool isCorLib = module.Assembly.IsCorLib(); typeVoid = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Void"), ElementType.Void); typeBoolean = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Boolean"), ElementType.Boolean); typeChar = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Char"), ElementType.Char); typeSByte = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "SByte"), ElementType.I1); typeByte = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Byte"), ElementType.U1); typeInt16 = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Int16"), ElementType.I2); typeUInt16 = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "UInt16"), ElementType.U2); typeInt32 = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Int32"), ElementType.I4); typeUInt32 = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "UInt32"), ElementType.U4); typeInt64 = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Int64"), ElementType.I8); typeUInt64 = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "UInt64"), ElementType.U8); typeSingle = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Single"), ElementType.R4); typeDouble = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Double"), ElementType.R8); typeString = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "String"), ElementType.String); typeTypedReference = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "TypedReference"), ElementType.TypedByRef); typeIntPtr = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "IntPtr"), ElementType.I); typeUIntPtr = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "UIntPtr"), ElementType.U); typeObject = new CorLibTypeSig(CreateCorLibTypeRef(isCorLib, "Object"), ElementType.Object); } ITypeDefOrRef CreateCorLibTypeRef(bool isCorLib, string name) { var tr = new TypeRefUser(module, "System", name, corLibAssemblyRef); if (isCorLib) { var td = module.Find(tr); if (td != null) return td; } return module.UpdateRowId(tr); } /// public TypeRef GetTypeRef(string @namespace, string name) { return module.UpdateRowId(new TypeRefUser(module, @namespace, name, corLibAssemblyRef)); } } } dnlib-2.1_VS2010/src/DotNet/CpuArch.cs000066400000000000000000000273411325033663500172340ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using dnlib.DotNet.Writer; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet { enum StubType { Export, EntryPoint, } abstract class CpuArch { static readonly Dictionary toCpuArch = new Dictionary { // 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 { Machine.I386, new X86CpuArch() }, { Machine.AMD64, new X64CpuArch() }, { Machine.IA64, new ItaniumCpuArch() }, { Machine.ARMNT, new ArmCpuArch() }, //TODO: Support ARM64 // { Machine.ARM64, new Arm64CpuArch() }, }; /// /// 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) { return toCpuArch.TryGetValue(machine, out cpuArch); } /// /// 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(IBinaryReader reader, IPEImage peImage, out uint funcRva) { bool b = TryGetExportedRvaFromStubCore(reader, peImage, out funcRva); Debug.Assert(b); return b; } protected abstract bool TryGetExportedRvaFromStubCore(IBinaryReader 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, BinaryWriter 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(IBinaryReader 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, BinaryWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva) { switch (stubType) { case StubType.Export: case StubType.EntryPoint: writer.Write((ushort)0);// padding writer.Write((ushort)0x25FF); writer.Write((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(IBinaryReader 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, BinaryWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva) { switch (stubType) { case StubType.Export: case StubType.EntryPoint: writer.Write((ushort)0);// padding writer.Write((ushort)0xA148); writer.Write(imageBase + managedFuncRva); writer.Write((ushort)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(IBinaryReader 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 = (long)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, BinaryWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva) { switch (stubType) { case StubType.Export: case StubType.EntryPoint: writer.Write(0x40A010180200480BUL); writer.Write(0x0004000000283024UL); writer.Write(0x5060101812000810UL); writer.Write(0x0080006000038004UL); writer.Write(imageBase + stubRva); writer.Write(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(IBinaryReader 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, BinaryWriter writer, ulong imageBase, uint stubRva, uint managedFuncRva) { switch (stubType) { case StubType.Export: case StubType.EntryPoint: writer.Write(0xF000F8DF); writer.Write((uint)imageBase + managedFuncRva); break; default: throw new ArgumentOutOfRangeException(); } } } } dnlib-2.1_VS2010/src/DotNet/CustomAttribute.cs000066400000000000000000000347501325033663500210470ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info 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 { /// /// A custom attribute /// public sealed class CustomAttribute : ICustomAttribute { ICustomAttributeType ctor; byte[] rawData; readonly ThreadSafe.IList arguments; readonly ThreadSafe.IList namedArguments; IBinaryReader blobReader; /// /// Gets/sets the custom attribute constructor /// public ICustomAttributeType Constructor { get { return ctor; } set { ctor = value; } } /// /// Gets the attribute type /// public ITypeDefOrRef AttributeType { get { var cat = ctor; return cat == null ? null : cat.DeclaringType; } } /// /// Gets the full name of the attribute type /// public string TypeFullName { get { var mrCtor = ctor as MemberRef; if (mrCtor != null) return mrCtor.GetDeclaringTypeFullName() ?? string.Empty; var mdCtor = ctor as MethodDef; if (mdCtor != null) { var declType = mdCtor.DeclaringType; if (declType != null) return declType.FullName; } return string.Empty; } } /// /// true if the raw custom attribute blob hasn't been parsed /// public bool IsRawBlob { get { return rawData != null; } } /// /// Gets the raw custom attribute blob or null if the CA was successfully parsed. /// public byte[] RawData { get { return rawData; } } /// /// Gets all constructor arguments /// public ThreadSafe.IList ConstructorArguments { get { return arguments; } } /// /// true if is not empty /// public bool HasConstructorArguments { get { return arguments.Count > 0; } } /// /// Gets all named arguments (field and property values) /// public ThreadSafe.IList NamedArguments { get { return namedArguments; } } /// /// true if is not empty /// public bool HasNamedArguments { get { return namedArguments.Count > 0; } } /// /// Gets all s that are field arguments /// public IEnumerable Fields { get { foreach (var namedArg in namedArguments.GetSafeEnumerable()) { if (namedArg.IsField) yield return namedArg; } } } /// /// Gets all s that are property arguments /// public IEnumerable Properties { get { foreach (var namedArg in namedArguments.GetSafeEnumerable()) { if (namedArg.IsProperty) yield return namedArg; } } } /// /// Constructor /// /// Custom attribute constructor /// Raw custom attribute blob public CustomAttribute(ICustomAttributeType ctor, byte[] rawData) : this(ctor, null, null, null) { this.rawData = rawData; } /// /// Constructor /// /// Custom attribute constructor public CustomAttribute(ICustomAttributeType ctor) : this(ctor, null, null, null) { } /// /// Constructor /// /// Custom attribute constructor /// Constructor arguments or null if none public CustomAttribute(ICustomAttributeType ctor, IEnumerable arguments) : this(ctor, arguments, null) { } /// /// Constructor /// /// Custom attribute constructor /// Named arguments or null if none public CustomAttribute(ICustomAttributeType ctor, IEnumerable namedArguments) : this(ctor, null, namedArguments) { } /// /// Constructor /// /// Custom attribute constructor /// 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) { } /// /// Constructor /// /// 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) { this.ctor = ctor; this.arguments = arguments == null ? ThreadSafeListCreator.Create() : ThreadSafeListCreator.Create(arguments); this.namedArguments = namedArguments == null ? ThreadSafeListCreator.Create() : ThreadSafeListCreator.Create(namedArguments); this.blobReader = blobReader; } /// /// Constructor /// /// 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) { this.ctor = ctor; this.arguments = arguments == null ? ThreadSafeListCreator.Create() : ThreadSafeListCreator.MakeThreadSafe(arguments); this.namedArguments = namedArguments == null ? ThreadSafeListCreator.Create() : ThreadSafeListCreator.MakeThreadSafe(namedArguments); this.blobReader = blobReader; } /// /// Gets the field named /// /// Name of field /// A instance or null if not found public CANamedArgument GetField(string name) { return 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); } /// /// Gets the property named /// /// Name of property /// A instance or null if not found public CANamedArgument GetProperty(string name) { return 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); } /// /// Gets the property/field named /// /// Name of property/field /// 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()) { if (namedArg.IsField == isField && UTF8String.ToSystemStringOrEmpty(namedArg.Name) == name) return namedArg; } return null; } /// /// Gets the property/field named /// /// Name of property/field /// 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()) { 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; } } /// /// A custom attribute constructor argument /// public struct CAArgument : ICloneable { TypeSig type; object value; /// /// Gets/sets the argument type /// public TypeSig Type { get { return type; } set { type = value; } } /// /// Gets/sets the argument value /// public object Value { get { return value; } set { this.value = value; } } /// /// Constructor /// /// Argument type public CAArgument(TypeSig type) { this.type = type; this.value = null; } /// /// Constructor /// /// Argument type /// Argument value public CAArgument(TypeSig type, object value) { this.type = type; this.value = value; } object ICloneable.Clone() { return Clone(); } /// /// Clones this instance and any s and s /// referenced from this instance. /// /// public 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()) 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); } } /// /// A custom attribute field/property argument /// public sealed class CANamedArgument : ICloneable { bool isField; TypeSig type; UTF8String name; CAArgument argument; /// /// true if it's a field /// public bool IsField { get { return isField; } set { isField = value; } } /// /// true if it's a property /// public bool IsProperty { get { return !isField; } set { isField = !value; } } /// /// Gets/sets the field/property type /// public TypeSig Type { get { return type; } set { type = value; } } /// /// Gets/sets the property/field name /// public UTF8String Name { get { return name; } set { name = value; } } /// /// Gets/sets the argument /// public CAArgument Argument { get { return argument; } set { argument = value; } } /// /// Gets/sets the argument type /// public TypeSig ArgumentType { get { return argument.Type; } set { argument.Type = value; } } /// /// Gets/sets the argument value /// public object Value { get { return argument.Value; } set { argument.Value = value; } } /// /// Default constructor /// public CANamedArgument() { } /// /// Constructor /// /// true if field, false if property public CANamedArgument(bool isField) { this.isField = isField; } /// /// Constructor /// /// true if field, false if property /// Field/property type public CANamedArgument(bool isField, TypeSig type) { this.isField = isField; this.type = type; } /// /// Constructor /// /// true if field, false if property /// Field/property type /// Name of field/property public CANamedArgument(bool isField, TypeSig type, UTF8String name) { this.isField = isField; this.type = type; this.name = name; } /// /// Constructor /// /// true if field, false if property /// Field/property type /// Name of field/property /// Field/property argument public CANamedArgument(bool isField, TypeSig type, UTF8String name, CAArgument argument) { this.isField = isField; this.type = type; this.name = name; this.argument = argument; } object ICloneable.Clone() { return Clone(); } /// /// Clones this instance and any s referenced from this instance. /// /// public CANamedArgument Clone() { return 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); } } } dnlib-2.1_VS2010/src/DotNet/CustomAttributeCollection.cs000066400000000000000000000101171325033663500230520ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using dnlib.Utils; using dnlib.Threading; namespace dnlib.DotNet { /// /// Stores s /// public class CustomAttributeCollection : LazyList { /// /// Default constructor /// public CustomAttributeCollection() { } /// /// Constructor /// /// Initial length of the list /// Context passed to /// Delegate instance that returns original values public CustomAttributeCollection(int length, object context, MFunc readOriginalValue) : base(length, context, readOriginalValue) { } /// /// Checks whether a custom attribute is present /// /// Full name of custom attribute type /// true if the custom attribute type is present, false otherwise public bool IsDefined(string fullName) { return Find(fullName) != null; } /// /// Removes all custom attributes of a certain type /// /// Full name of custom attribute type that should be removed public void RemoveAll(string fullName) { this.IterateAllReverse((tsList, index, value) => { if (value.TypeFullName == fullName) RemoveAt_NoLock(index); }); } /// /// Finds a custom attribute /// /// Full name of custom attribute type /// A or null if it wasn't found public CustomAttribute Find(string fullName) { foreach (var ca in this.GetSafeEnumerable()) { if (ca != null && ca.TypeFullName == fullName) return ca; } return null; } /// /// Finds all custom attributes of a certain type /// /// Full name of custom attribute type /// All s of the requested type public IEnumerable FindAll(string fullName) { foreach (var ca in this.GetSafeEnumerable()) { if (ca != null && ca.TypeFullName == fullName) yield return ca; } } /// /// Finds a custom attribute /// /// Custom attribute type /// The first found or null if none found public CustomAttribute Find(IType attrType) { return Find(attrType, 0); } /// /// Finds a custom attribute /// /// Custom attribute type /// Attribute type comparison flags /// The first found or null if none found public CustomAttribute Find(IType attrType, SigComparerOptions options) { var comparer = new SigComparer(options); foreach (var ca in this.GetSafeEnumerable()) { if (comparer.Equals(ca.AttributeType, attrType)) return ca; } return null; } /// /// Finds all custom attributes of a certain type /// /// Custom attribute type /// All s of the requested type public IEnumerable FindAll(IType attrType) { return FindAll(attrType, 0); } /// /// Finds all custom attributes of a certain type /// /// Custom attribute type /// Attribute type comparison flags /// All s of the requested type public IEnumerable FindAll(IType attrType, SigComparerOptions options) { var comparer = new SigComparer(options); foreach (var ca in this.GetSafeEnumerable()) { if (comparer.Equals(ca.AttributeType, attrType)) yield return ca; } } } } dnlib-2.1_VS2010/src/DotNet/CustomAttributeReader.cs000066400000000000000000000516371325033663500221750ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; using dnlib.IO; using dnlib.Threading; namespace dnlib.DotNet { /// /// Searches for a type according to custom attribute search rules: first try the /// current assembly, and if that fails, try mscorlib /// sealed class CAAssemblyRefFinder : IAssemblyRefFinder { readonly ModuleDef module; /// /// Constructor /// /// The module to search first public CAAssemblyRefFinder(ModuleDef module) { this.module = module; } /// public AssemblyRef FindAssemblyRef(TypeRef nonNestedTypeRef) { var modAsm = module.Assembly; if (modAsm != null) { var type = modAsm.Find(nonNestedTypeRef); if (type != null) return module.UpdateRowId(new AssemblyRefUser(modAsm)); } else if (module.Find(nonNestedTypeRef) != null) return AssemblyRef.CurrentAssembly; var corLibAsm = module.Context.AssemblyResolver.Resolve(module.CorLibTypes.AssemblyRef, module); if (corLibAsm != null) { var type = corLibAsm.Find(nonNestedTypeRef); if (type != null) return module.CorLibTypes.AssemblyRef; } if (modAsm != null) return module.UpdateRowId(new AssemblyRefUser(modAsm)); return AssemblyRef.CurrentAssembly; } } /// /// Thrown by CustomAttributeReader when it fails to parse a custom attribute blob /// [Serializable] public class CABlobParserException : Exception { /// /// Default constructor /// public CABlobParserException() { } /// /// Constructor /// /// Error message public CABlobParserException(string message) : base(message) { } /// /// Constructor /// /// Error message /// Other exception public CABlobParserException(string message, Exception innerException) : base(message, innerException) { } /// /// Constructor /// /// /// protected CABlobParserException(SerializationInfo info, StreamingContext context) : base(info, context) { } } /// /// Reads custom attributes from the #Blob stream /// public struct CustomAttributeReader : IDisposable { readonly ModuleDef module; readonly IBinaryReader reader; readonly GenericParamContext gpContext; GenericArguments genericArguments; RecursionCounter recursionCounter; bool verifyReadAllBytes; readonly bool ownReader; /// /// Reads a custom attribute /// /// Reader module /// Custom attribute constructor /// Offset of custom attribute in the #Blob stream /// A new instance public static CustomAttribute Read(ModuleDefMD readerModule, ICustomAttributeType ctor, uint offset) { return Read(readerModule, ctor, offset, new GenericParamContext()); } /// /// Reads a custom attribute /// /// Reader module /// Custom attribute constructor /// Offset of custom attribute in the #Blob stream /// Generic parameter context /// A new instance public static CustomAttribute Read(ModuleDefMD readerModule, ICustomAttributeType ctor, uint offset, GenericParamContext gpContext) { using (var reader = new CustomAttributeReader(readerModule, offset, gpContext)) { try { if (ctor == null) return reader.CreateRaw(ctor); return reader.Read(ctor); } catch (CABlobParserException) { return reader.CreateRaw(ctor); } catch (IOException) { return reader.CreateRaw(ctor); } } } CustomAttribute CreateRaw(ICustomAttributeType ctor) { return new CustomAttribute(ctor, GetRawBlob()); } /// /// Reads a custom attribute /// /// Owner module /// CA blob /// Custom attribute constructor /// A new instance public static CustomAttribute Read(ModuleDef module, byte[] caBlob, ICustomAttributeType ctor) { return Read(module, MemoryImageStream.Create(caBlob), ctor, new GenericParamContext()); } /// /// Reads a custom attribute /// /// Owner module /// A stream positioned at the the first byte of the CA blob /// Custom attribute constructor /// A new instance public static CustomAttribute Read(ModuleDef module, IBinaryReader stream, ICustomAttributeType ctor) { return Read(module, stream, ctor, new GenericParamContext()); } /// /// Reads a custom attribute /// /// Owner module /// CA blob /// Custom attribute constructor /// Generic parameter context /// A new instance public static CustomAttribute Read(ModuleDef module, byte[] caBlob, ICustomAttributeType ctor, GenericParamContext gpContext) { return Read(module, MemoryImageStream.Create(caBlob), ctor, gpContext); } /// /// Reads a custom attribute /// /// Owner module /// A stream positioned at the the first byte of the CA blob /// Custom attribute constructor /// Generic parameter context /// A new instance public static CustomAttribute Read(ModuleDef module, IBinaryReader stream, ICustomAttributeType ctor, GenericParamContext gpContext) { using (var reader = new CustomAttributeReader(module, stream, gpContext)) { try { if (stream == null || ctor == null) return reader.CreateRaw(ctor); return reader.Read(ctor); } catch (CABlobParserException) { return reader.CreateRaw(ctor); } catch (IOException) { return reader.CreateRaw(ctor); } } } /// /// Reads custom attribute named arguments /// /// Owner module /// A stream positioned at the the first byte of the CA blob /// Number of named arguments to read from /// Generic parameter context /// A list of s or null if some error /// occurred. internal static List ReadNamedArguments(ModuleDef module, IBinaryReader stream, int numNamedArgs, GenericParamContext gpContext) { try { using (var reader = new CustomAttributeReader(module, stream, false, gpContext)) return reader.ReadNamedArguments(numNamedArgs); } catch (CABlobParserException) { return null; } catch (IOException) { return null; } } CustomAttributeReader(ModuleDefMD readerModule, uint offset, GenericParamContext gpContext) { this.module = readerModule; this.reader = readerModule.BlobStream.CreateStream(offset); this.ownReader = true; this.genericArguments = null; this.recursionCounter = new RecursionCounter(); this.verifyReadAllBytes = false; this.gpContext = gpContext; } CustomAttributeReader(ModuleDef module, IBinaryReader reader, GenericParamContext gpContext) { this.module = module; this.reader = reader; this.ownReader = false; this.genericArguments = null; this.recursionCounter = new RecursionCounter(); this.verifyReadAllBytes = false; this.gpContext = gpContext; } CustomAttributeReader(ModuleDef module, IBinaryReader reader, bool ownRerader, GenericParamContext gpContext) { this.module = module; this.reader = reader; this.ownReader = ownRerader; this.genericArguments = null; this.recursionCounter = new RecursionCounter(); this.verifyReadAllBytes = false; this.gpContext = gpContext; } byte[] GetRawBlob() { return reader.ReadAllBytes(); } CustomAttribute Read(ICustomAttributeType ctor) { var methodSig = ctor == null ? null : ctor.MethodSig; if (methodSig == null) throw new CABlobParserException("ctor is null or not a method"); var mrCtor = ctor as MemberRef; if (mrCtor != null) { var owner = mrCtor.Class as TypeSpec; if (owner != null) { var gis = owner.TypeSig as GenericInstSig; if (gis != null) { genericArguments = new GenericArguments(); genericArguments.PushTypeArgs(gis.GenericArguments); } } } bool isEmpty = methodSig.Params.Count == 0 && reader.Position == reader.Length; if (!isEmpty && reader.ReadUInt16() != 1) throw new CABlobParserException("Invalid CA blob prolog"); var ctorArgs = new List(methodSig.Params.Count); foreach (var arg in methodSig.Params.GetSafeEnumerable()) ctorArgs.Add(ReadFixedArg(FixTypeSig(arg))); // Some tools don't write the next ushort if there are no named arguments. int numNamedArgs = reader.Position == reader.Length ? 0 : reader.ReadUInt16(); var namedArgs = ReadNamedArguments(numNamedArgs); // verifyReadAllBytes will be set when we guess the underlying type of an enum. // To make sure we guessed right, verify that we read all bytes. if (verifyReadAllBytes && reader.Position != reader.Length) throw new CABlobParserException("Not all CA blob bytes were read"); return new CustomAttribute(ctor, ctorArgs, namedArgs, CloneBlobReader(reader)); } static IBinaryReader CloneBlobReader(IBinaryReader reader) { if (reader == null) return null; var imgStream = reader as IImageStream; if (imgStream != null) return imgStream.Clone(); return MemoryImageStream.Create(reader.ReadAllBytes()); } List ReadNamedArguments(int numNamedArgs) { var namedArgs = new List(numNamedArgs); for (int i = 0; i < numNamedArgs; i++) { if (reader.Position == reader.Length) break; namedArgs.Add(ReadNamedArgument()); } return namedArgs; } TypeSig FixTypeSig(TypeSig type) { return SubstituteGenericParameter(type.RemoveModifiers()).RemoveModifiers(); } TypeSig SubstituteGenericParameter(TypeSig type) { if (genericArguments == null) return type; return genericArguments.Resolve(type); } CAArgument ReadFixedArg(TypeSig argType) { if (!recursionCounter.Increment()) throw new CABlobParserException("Too much recursion"); if (argType == null) throw new CABlobParserException("null argType"); CAArgument result; var arrayType = argType as SZArraySig; if (arrayType != null) result = ReadArrayArgument(arrayType); else result = ReadElem(argType); recursionCounter.Decrement(); return result; } CAArgument ReadElem(TypeSig argType) { if (argType == null) throw new CABlobParserException("null argType"); TypeSig realArgType; var value = ReadValue((SerializationType)argType.ElementType, argType, out realArgType); if (realArgType == null) throw new CABlobParserException("Invalid arg type"); // One example when this is true is when prop/field type is object and // value type is string[] if (value is CAArgument) return (CAArgument)value; return new CAArgument(realArgType, value); } object ReadValue(SerializationType etype, TypeSig argType, out TypeSig realArgType) { if (!recursionCounter.Increment()) throw new CABlobParserException("Too much recursion"); object result; switch (etype) { case SerializationType.Boolean: realArgType = module.CorLibTypes.Boolean; result = reader.ReadByte() != 0; break; case SerializationType.Char: realArgType = module.CorLibTypes.Char; result = (char)reader.ReadUInt16(); break; case SerializationType.I1: realArgType = module.CorLibTypes.SByte; result = reader.ReadSByte(); break; case SerializationType.U1: realArgType = module.CorLibTypes.Byte; result = reader.ReadByte(); break; case SerializationType.I2: realArgType = module.CorLibTypes.Int16; result = reader.ReadInt16(); break; case SerializationType.U2: realArgType = module.CorLibTypes.UInt16; result = reader.ReadUInt16(); break; case SerializationType.I4: realArgType = module.CorLibTypes.Int32; result = reader.ReadInt32(); break; case SerializationType.U4: realArgType = module.CorLibTypes.UInt32; result = reader.ReadUInt32(); break; case SerializationType.I8: realArgType = module.CorLibTypes.Int64; result = reader.ReadInt64(); break; case SerializationType.U8: realArgType = module.CorLibTypes.UInt64; result = reader.ReadUInt64(); break; case SerializationType.R4: realArgType = module.CorLibTypes.Single; result = reader.ReadSingle(); break; case SerializationType.R8: realArgType = module.CorLibTypes.Double; result = reader.ReadDouble(); break; case SerializationType.String: realArgType = module.CorLibTypes.String; result = ReadUTF8String(); break; // It's ET.ValueType if it's eg. a ctor enum arg type case (SerializationType)ElementType.ValueType: if (argType == null) throw new CABlobParserException("Invalid element type"); realArgType = argType; result = ReadEnumValue(GetEnumUnderlyingType(argType)); break; // It's ET.Object if it's a ctor object arg type case (SerializationType)ElementType.Object: case SerializationType.TaggedObject: realArgType = ReadFieldOrPropType(); var arraySig = realArgType as SZArraySig; if (arraySig != null) result = ReadArrayArgument(arraySig); else { TypeSig tmpType; result = ReadValue((SerializationType)realArgType.ElementType, realArgType, out tmpType); } break; // It's ET.Class if it's eg. a ctor System.Type arg type case (SerializationType)ElementType.Class: var tdr = argType as TypeDefOrRefSig; if (tdr != null && tdr.DefinitionAssembly.IsCorLib() && tdr.Namespace == "System") { if (tdr.TypeName == "Type") { result = ReadValue(SerializationType.Type, tdr, out realArgType); break; } if (tdr.TypeName == "String") { result = ReadValue(SerializationType.String, tdr, out realArgType); break; } if (tdr.TypeName == "Object") { result = ReadValue(SerializationType.TaggedObject, tdr, out realArgType); break; } } // Assume it's an enum that couldn't be resolved realArgType = argType; result = ReadEnumValue(null); break; case SerializationType.Type: realArgType = argType; result = ReadType(true); break; case SerializationType.Enum: realArgType = ReadType(false); result = ReadEnumValue(GetEnumUnderlyingType(realArgType)); break; default: throw new CABlobParserException("Invalid element type"); } recursionCounter.Decrement(); return result; } object ReadEnumValue(TypeSig underlyingType) { if (underlyingType != null) { if (underlyingType.ElementType < ElementType.Boolean || underlyingType.ElementType > ElementType.U8) throw new CABlobParserException("Invalid enum underlying type"); TypeSig realArgType; return ReadValue((SerializationType)underlyingType.ElementType, underlyingType, out realArgType); } // We couldn't resolve the type ref. It should be an enum, but we don't know for sure. // Most enums use Int32 as the underlying type. Assume that's true also in this case. // Since we're guessing, verify that we've read all CA blob bytes. If we haven't, then // we probably guessed wrong. verifyReadAllBytes = true; return reader.ReadInt32(); } TypeSig ReadType(bool canReturnNull) { var name = ReadUTF8String(); if (canReturnNull && (object)name == null) return null; var asmRefFinder = new CAAssemblyRefFinder(module); var type = TypeNameParser.ParseAsTypeSigReflection(module, UTF8String.ToSystemStringOrEmpty(name), asmRefFinder, gpContext); if (type == null) throw new CABlobParserException("Could not parse type"); return type; } /// /// Gets the enum's underlying type /// /// An enum type /// The underlying type or null if we couldn't resolve the type ref /// If is not an enum or null static TypeSig GetEnumUnderlyingType(TypeSig type) { if (type == null) throw new CABlobParserException("null enum type"); var td = GetTypeDef(type); if (td == null) return null; if (!td.IsEnum) throw new CABlobParserException("Not an enum"); return td.GetEnumUnderlyingType().RemoveModifiers(); } /// /// Converts to a , possibly resolving /// a /// /// The type /// A or null if we couldn't resolve the /// or if is a type spec static TypeDef GetTypeDef(TypeSig type) { var tdr = type as TypeDefOrRefSig; if (tdr != null) { var td = tdr.TypeDef; if (td != null) return td; var tr = tdr.TypeRef; if (tr != null) return tr.Resolve(); } return null; } CAArgument ReadArrayArgument(SZArraySig arrayType) { if (!recursionCounter.Increment()) throw new CABlobParserException("Too much recursion"); var arg = new CAArgument(arrayType); int arrayCount = reader.ReadInt32(); if (arrayCount == -1) { // -1 if it's null } else if (arrayCount < 0) throw new CABlobParserException("Array is too big"); else { var array = ThreadSafeListCreator.Create(arrayCount); arg.Value = array; for (int i = 0; i < arrayCount; i++) array.Add(ReadFixedArg(FixTypeSig(arrayType.Next))); } recursionCounter.Decrement(); return arg; } CANamedArgument ReadNamedArgument() { bool isField; switch ((SerializationType)reader.ReadByte()) { case SerializationType.Property:isField = false; break; case SerializationType.Field: isField = true; break; default: throw new CABlobParserException("Named argument is not a field/property"); } TypeSig fieldPropType = ReadFieldOrPropType(); var name = ReadUTF8String(); var argument = ReadFixedArg(fieldPropType); return new CANamedArgument(isField, fieldPropType, name, argument); } TypeSig ReadFieldOrPropType() { if (!recursionCounter.Increment()) throw new CABlobParserException("Too much recursion"); TypeSig result; switch ((SerializationType)reader.ReadByte()) { case SerializationType.Boolean: result = module.CorLibTypes.Boolean; break; case SerializationType.Char: result = module.CorLibTypes.Char; break; case SerializationType.I1: result = module.CorLibTypes.SByte; break; case SerializationType.U1: result = module.CorLibTypes.Byte; break; case SerializationType.I2: result = module.CorLibTypes.Int16; break; case SerializationType.U2: result = module.CorLibTypes.UInt16; break; case SerializationType.I4: result = module.CorLibTypes.Int32; break; case SerializationType.U4: result = module.CorLibTypes.UInt32; break; case SerializationType.I8: result = module.CorLibTypes.Int64; break; case SerializationType.U8: result = module.CorLibTypes.UInt64; break; case SerializationType.R4: result = module.CorLibTypes.Single; break; case SerializationType.R8: result = module.CorLibTypes.Double; break; case SerializationType.String: result = module.CorLibTypes.String; break; case SerializationType.SZArray: result = new SZArraySig(ReadFieldOrPropType()); break; case SerializationType.Type: result = new ClassSig(module.CorLibTypes.GetTypeRef("System", "Type")); break; case SerializationType.TaggedObject: result = module.CorLibTypes.Object; break; case SerializationType.Enum: result = ReadType(false); break; default: throw new CABlobParserException("Invalid type"); } recursionCounter.Decrement(); return result; } UTF8String ReadUTF8String() { if (reader.ReadByte() == 0xFF) return null; reader.Position--; uint len; if (!reader.ReadCompressedUInt32(out len)) throw new CABlobParserException("Could not read compressed UInt32"); if (len == 0) return UTF8String.Empty; return new UTF8String(reader.ReadBytes((int)len)); } /// public void Dispose() { if (ownReader && reader != null) reader.Dispose(); } } } dnlib-2.1_VS2010/src/DotNet/DeclSecurity.cs000066400000000000000000000171151325033663500203040ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the DeclSecurity table /// [DebuggerDisplay("{Action} Count={SecurityAttributes.Count}")] public abstract class DeclSecurity : IHasCustomAttribute, IHasCustomDebugInformation { /// /// The row id in its table /// protected uint rid; /// public MDToken MDToken { get { return new MDToken(Table.DeclSecurity, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 8; } } /// /// From column DeclSecurity.Action /// public SecurityAction Action { get { return action; } set { action = value; } } /// protected SecurityAction action; /// /// From column DeclSecurity.PermissionSet /// public ThreadSafe.IList SecurityAttributes { get { if (securityAttributes == null) InitializeSecurityAttributes(); return securityAttributes; } } /// protected ThreadSafe.IList securityAttributes; /// Initializes protected virtual void InitializeSecurityAttributes() { Interlocked.CompareExchange(ref securityAttributes, ThreadSafeListCreator.Create(), null); } /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 8; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// /// true if is not empty /// public bool HasSecurityAttributes { get { return SecurityAttributes.Count > 0; } } /// /// Gets the blob data or null if there's none /// /// Blob data or null public abstract byte[] GetBlob(); /// /// Returns the .NET 1.x XML string or null if it's not a .NET 1.x format /// /// public string GetNet1xXmlString() { return GetNet1xXmlStringInternal(SecurityAttributes); } internal static string GetNet1xXmlStringInternal(IList secAttrs) { if (secAttrs == null || secAttrs.Count != 1) return null; var sa = secAttrs[0]; if (sa == null || sa.TypeFullName != "System.Security.Permissions.PermissionSetAttribute") return null; if (sa.NamedArguments.Count != 1) return null; var na = sa.NamedArguments[0]; if (na == null || !na.IsProperty || na.Name != "XML") return null; if (na.ArgumentType.GetElementType() != ElementType.String) return null; var arg = na.Argument; if (arg.Type.GetElementType() != ElementType.String) return null; var utf8 = arg.Value as UTF8String; if ((object)utf8 != null) return utf8; var s = arg.Value as string; if (s != null) return s; return null; } } /// /// A DeclSecurity row created by the user and not present in the original .NET file /// public class DeclSecurityUser : DeclSecurity { /// /// Default constructor /// public DeclSecurityUser() { } /// /// Constructor /// /// The security action /// The security attributes (now owned by this) public DeclSecurityUser(SecurityAction action, IList securityAttrs) { this.action = action; this.securityAttributes = ThreadSafeListCreator.MakeThreadSafe(securityAttrs); } /// public override byte[] GetBlob() { return null; } } /// /// Created from a row in the DeclSecurity table /// sealed class DeclSecurityMD : DeclSecurity, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; readonly uint permissionSet; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeSecurityAttributes() { var gpContext = new GenericParamContext(); var tmp = DeclSecurityReader.Read(readerModule, permissionSet, gpContext); Interlocked.CompareExchange(ref securityAttributes, tmp, null); } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.DeclSecurity, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); var gpContext = new GenericParamContext(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), gpContext, list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this DeclSecurity row /// Row ID /// If is null /// If is invalid public DeclSecurityMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.DeclSecurityTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("DeclSecurity rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; this.permissionSet = readerModule.TablesStream.ReadDeclSecurityRow(origRid, out this.action); } /// public override byte[] GetBlob() { return readerModule.BlobStream.Read(permissionSet); } } } dnlib-2.1_VS2010/src/DotNet/DeclSecurityReader.cs000066400000000000000000000132121325033663500214210ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Text; using dnlib.IO; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// Reads DeclSecurity blobs /// public struct DeclSecurityReader : IDisposable { readonly IBinaryReader reader; readonly ModuleDef module; readonly GenericParamContext gpContext; /// /// Reads a DeclSecurity blob /// /// Module that will own the returned list /// #Blob offset of DeclSecurity signature /// A list of s public static ThreadSafe.IList Read(ModuleDefMD module, uint sig) { return Read(module, module.BlobStream.CreateStream(sig), new GenericParamContext()); } /// /// Reads a DeclSecurity blob /// /// Module that will own the returned list /// #Blob offset of DeclSecurity signature /// Generic parameter context /// A list of s public static ThreadSafe.IList Read(ModuleDefMD module, uint sig, GenericParamContext gpContext) { return Read(module, module.BlobStream.CreateStream(sig), gpContext); } /// /// Reads a DeclSecurity blob /// /// Module that will own the returned list /// DeclSecurity blob /// A list of s public static ThreadSafe.IList Read(ModuleDef module, byte[] blob) { return Read(module, MemoryImageStream.Create(blob), new GenericParamContext()); } /// /// Reads a DeclSecurity blob /// /// Module that will own the returned list /// DeclSecurity blob /// Generic parameter context/// /// A list of s public static ThreadSafe.IList Read(ModuleDef module, byte[] blob, GenericParamContext gpContext) { return Read(module, MemoryImageStream.Create(blob), gpContext); } /// /// Reads a DeclSecurity blob /// /// Module that will own the returned list /// DeclSecurity stream that will be owned by us /// A list of s public static ThreadSafe.IList Read(ModuleDef module, IBinaryReader signature) { return Read(module, signature, new GenericParamContext()); } /// /// Reads a DeclSecurity blob /// /// Module that will own the returned list /// DeclSecurity stream that will be owned by us /// Generic parameter context /// A list of s public static ThreadSafe.IList Read(ModuleDef module, IBinaryReader signature, GenericParamContext gpContext) { using (var reader = new DeclSecurityReader(module, signature, gpContext)) return reader.Read(); } DeclSecurityReader(ModuleDef module, IBinaryReader reader, GenericParamContext gpContext) { this.reader = reader; this.module = module; this.gpContext = gpContext; } ThreadSafe.IList Read() { try { if (reader.Position >= reader.Length) return ThreadSafeListCreator.Create(); if (reader.ReadByte() == '.') return ReadBinaryFormat(); reader.Position--; return ReadXmlFormat(); } catch { return ThreadSafeListCreator.Create(); } } /// /// Reads the new (.NET 2.0+) DeclSecurity blob format /// /// ThreadSafe.IList ReadBinaryFormat() { int numAttrs = (int)reader.ReadCompressedUInt32(); var list = ThreadSafeListCreator.Create(numAttrs); for (int i = 0; i < numAttrs; i++) { var name = ReadUTF8String(); // Use CA search rules. Some tools don't write the fully qualified name. var attrRef = TypeNameParser.ParseReflection(module, UTF8String.ToSystemStringOrEmpty(name), new CAAssemblyRefFinder(module), gpContext); /*int blobLength = (int)*/reader.ReadCompressedUInt32(); int numNamedArgs = (int)reader.ReadCompressedUInt32(); var namedArgs = CustomAttributeReader.ReadNamedArguments(module, reader, numNamedArgs, gpContext); if (namedArgs == null) throw new ApplicationException("Could not read named arguments"); list.Add(new SecurityAttribute(attrRef, namedArgs)); } return list; } /// /// Reads the old (.NET 1.x) DeclSecurity blob format /// /// ThreadSafe.IList ReadXmlFormat() { var xml = Encoding.Unicode.GetString(reader.ReadAllBytes()); var sa = SecurityAttribute.CreateFromXml(module, xml); return ThreadSafeListCreator.Create(sa); } UTF8String ReadUTF8String() { uint len = reader.ReadCompressedUInt32(); return len == 0 ? UTF8String.Empty : new UTF8String(reader.ReadBytes((int)len)); } /// public void Dispose() { if (reader != null) reader.Dispose(); } } } dnlib-2.1_VS2010/src/DotNet/ElementType.cs000066400000000000000000000126071325033663500201410ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// See CorHdr.h/CorElementType /// public enum ElementType : byte { /// End = 0x00, /// System.Void Void = 0x01, /// System.Boolean Boolean = 0x02, /// System.Char Char = 0x03, /// System.SByte I1 = 0x04, /// System.Byte U1 = 0x05, /// System.Int16 I2 = 0x06, /// System.UInt16 U2 = 0x07, /// System.Int32 I4 = 0x08, /// System.UInt32 U4 = 0x09, /// System.Int64 I8 = 0x0A, /// System.UInt64 U8 = 0x0B, /// System.Single R4 = 0x0C, /// System.Double R8 = 0x0D, /// System.String String = 0x0E, /// Pointer type (*) Ptr = 0x0F, /// ByRef type (&) ByRef = 0x10, /// Value type ValueType = 0x11, /// Reference type Class = 0x12, /// Type generic parameter Var = 0x13, /// Multidimensional array ([*], [,], [,,], ...) Array = 0x14, /// Generic instance type GenericInst = 0x15, /// Typed byref TypedByRef = 0x16, /// Value array (don't use) ValueArray = 0x17, /// System.IntPtr I = 0x18, /// System.UIntPtr U = 0x19, /// native real (don't use) R = 0x1A, /// Function pointer FnPtr = 0x1B, /// System.Object Object = 0x1C, /// Single-dimension, zero lower bound array ([]) SZArray = 0x1D, /// Method generic parameter MVar = 0x1E, /// Required C modifier CModReqd = 0x1F, /// Optional C modifier CModOpt = 0x20, /// Used internally by the CLR (don't use) Internal = 0x21, /// Module (don't use) Module = 0x3F, /// Sentinel (method sigs only) Sentinel = 0x41, /// Pinned type (locals only) Pinned = 0x45, } public static partial class Extensions { /// /// Returns true if it's an integer or a floating point type /// /// Element type /// public static bool IsPrimitive(this ElementType etype) { switch (etype) { case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.I: case ElementType.U: case ElementType.R: return true; default: return false; } } /// /// Returns the size of the element type in bytes or -1 if it's unknown /// /// Element type /// Size of a pointer /// public static int GetPrimitiveSize(this ElementType etype, int ptrSize = -1) { switch (etype) { case ElementType.Boolean: case ElementType.I1: case ElementType.U1: return 1; case ElementType.Char: case ElementType.I2: case ElementType.U2: return 2; case ElementType.I4: case ElementType.U4: case ElementType.R4: return 4; case ElementType.I8: case ElementType.U8: case ElementType.R8: return 8; case ElementType.Ptr: case ElementType.FnPtr: case ElementType.I: case ElementType.U: return ptrSize; default: return -1; } } /// /// Checks whether it's a value type /// /// this /// true if it's a value type, false if it's not a value type or /// if we couldn't determine whether it's a value type. Eg., it could be a generic /// instance type. public static bool IsValueType(this ElementType etype) { switch (etype) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.ValueType: case ElementType.TypedByRef: case ElementType.ValueArray: case ElementType.I: case ElementType.U: case ElementType.R: return true; case ElementType.GenericInst: // We don't have enough info to determine whether this is a value type return false; case ElementType.End: case ElementType.String: case ElementType.Ptr: case ElementType.ByRef: case ElementType.Class: case ElementType.Var: case ElementType.Array: case ElementType.FnPtr: case ElementType.Object: case ElementType.SZArray: case ElementType.MVar: case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Internal: case ElementType.Module: case ElementType.Sentinel: case ElementType.Pinned: default: return false; } } } } dnlib-2.1_VS2010/src/DotNet/Emit/000077500000000000000000000000001325033663500162475ustar00rootroot00000000000000dnlib-2.1_VS2010/src/DotNet/Emit/Code.cs000066400000000000000000000137151325033663500174570ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Emit { /// /// A CIL opcode. If the high byte is 0 or if it's , it's a 1-byte opcode, /// else it's a two-byte opcode and the highest byte is the first byte of the opcode. /// public enum Code : ushort { #pragma warning disable 1591 // disable XML doc warning UNKNOWN1 = 0x0100, UNKNOWN2 = 0x0101, Add = 0x0058, Add_Ovf = 0x00D6, Add_Ovf_Un = 0x00D7, And = 0x005F, Arglist = 0xFE00, Beq = 0x003B, Beq_S = 0x002E, Bge = 0x003C, Bge_S = 0x002F, Bge_Un = 0x0041, Bge_Un_S = 0x0034, Bgt = 0x003D, Bgt_S = 0x0030, Bgt_Un = 0x0042, Bgt_Un_S = 0x0035, Ble = 0x003E, Ble_S = 0x0031, Ble_Un = 0x0043, Ble_Un_S = 0x0036, Blt = 0x003F, Blt_S = 0x0032, Blt_Un = 0x0044, Blt_Un_S = 0x0037, Bne_Un = 0x0040, Bne_Un_S = 0x0033, Box = 0x008C, Br = 0x0038, Br_S = 0x002B, Break = 0x0001, Brfalse = 0x0039, Brfalse_S = 0x002C, Brtrue = 0x003A, Brtrue_S = 0x002D, Call = 0x0028, Calli = 0x0029, Callvirt = 0x006F, Castclass = 0x0074, Ceq = 0xFE01, Cgt = 0xFE02, Cgt_Un = 0xFE03, Ckfinite = 0x00C3, Clt = 0xFE04, Clt_Un = 0xFE05, Constrained = 0xFE16, Conv_I = 0x00D3, Conv_I1 = 0x0067, Conv_I2 = 0x0068, Conv_I4 = 0x0069, Conv_I8 = 0x006A, Conv_Ovf_I = 0x00D4, Conv_Ovf_I_Un = 0x008A, Conv_Ovf_I1 = 0x00B3, Conv_Ovf_I1_Un = 0x0082, Conv_Ovf_I2 = 0x00B5, Conv_Ovf_I2_Un = 0x0083, Conv_Ovf_I4 = 0x00B7, Conv_Ovf_I4_Un = 0x0084, Conv_Ovf_I8 = 0x00B9, Conv_Ovf_I8_Un = 0x0085, Conv_Ovf_U = 0x00D5, Conv_Ovf_U_Un = 0x008B, Conv_Ovf_U1 = 0x00B4, Conv_Ovf_U1_Un = 0x0086, Conv_Ovf_U2 = 0x00B6, Conv_Ovf_U2_Un = 0x0087, Conv_Ovf_U4 = 0x00B8, Conv_Ovf_U4_Un = 0x0088, Conv_Ovf_U8 = 0x00BA, Conv_Ovf_U8_Un = 0x0089, Conv_R_Un = 0x0076, Conv_R4 = 0x006B, Conv_R8 = 0x006C, Conv_U = 0x00E0, Conv_U1 = 0x00D2, Conv_U2 = 0x00D1, Conv_U4 = 0x006D, Conv_U8 = 0x006E, Cpblk = 0xFE17, Cpobj = 0x0070, Div = 0x005B, Div_Un = 0x005C, Dup = 0x0025, Endfilter = 0xFE11, Endfinally = 0x00DC, Initblk = 0xFE18, Initobj = 0xFE15, Isinst = 0x0075, Jmp = 0x0027, Ldarg = 0xFE09, Ldarg_0 = 0x0002, Ldarg_1 = 0x0003, Ldarg_2 = 0x0004, Ldarg_3 = 0x0005, Ldarg_S = 0x000E, Ldarga = 0xFE0A, Ldarga_S = 0x000F, Ldc_I4 = 0x0020, Ldc_I4_0 = 0x0016, Ldc_I4_1 = 0x0017, Ldc_I4_2 = 0x0018, Ldc_I4_3 = 0x0019, Ldc_I4_4 = 0x001A, Ldc_I4_5 = 0x001B, Ldc_I4_6 = 0x001C, Ldc_I4_7 = 0x001D, Ldc_I4_8 = 0x001E, Ldc_I4_M1 = 0x0015, Ldc_I4_S = 0x001F, Ldc_I8 = 0x0021, Ldc_R4 = 0x0022, Ldc_R8 = 0x0023, Ldelem = 0x00A3, Ldelem_I = 0x0097, Ldelem_I1 = 0x0090, Ldelem_I2 = 0x0092, Ldelem_I4 = 0x0094, Ldelem_I8 = 0x0096, Ldelem_R4 = 0x0098, Ldelem_R8 = 0x0099, Ldelem_Ref = 0x009A, Ldelem_U1 = 0x0091, Ldelem_U2 = 0x0093, Ldelem_U4 = 0x0095, Ldelema = 0x008F, Ldfld = 0x007B, Ldflda = 0x007C, Ldftn = 0xFE06, Ldind_I = 0x004D, Ldind_I1 = 0x0046, Ldind_I2 = 0x0048, Ldind_I4 = 0x004A, Ldind_I8 = 0x004C, Ldind_R4 = 0x004E, Ldind_R8 = 0x004F, Ldind_Ref = 0x0050, Ldind_U1 = 0x0047, Ldind_U2 = 0x0049, Ldind_U4 = 0x004B, Ldlen = 0x008E, Ldloc = 0xFE0C, Ldloc_0 = 0x0006, Ldloc_1 = 0x0007, Ldloc_2 = 0x0008, Ldloc_3 = 0x0009, Ldloc_S = 0x0011, Ldloca = 0xFE0D, Ldloca_S = 0x0012, Ldnull = 0x0014, Ldobj = 0x0071, Ldsfld = 0x007E, Ldsflda = 0x007F, Ldstr = 0x0072, Ldtoken = 0x00D0, Ldvirtftn = 0xFE07, Leave = 0x00DD, Leave_S = 0x00DE, Localloc = 0xFE0F, Mkrefany = 0x00C6, Mul = 0x005A, Mul_Ovf = 0x00D8, Mul_Ovf_Un = 0x00D9, Neg = 0x0065, Newarr = 0x008D, Newobj = 0x0073, // No = 0xFE19, // Not supported by MS' CLI and must be parsed as an opcode without an operand Nop = 0x0000, Not = 0x0066, Or = 0x0060, Pop = 0x0026, Prefix1 = 0x00FE, Prefix2 = 0x00FD, Prefix3 = 0x00FC, Prefix4 = 0x00FB, Prefix5 = 0x00FA, Prefix6 = 0x00F9, Prefix7 = 0x00F8, Prefixref = 0x00FF, Readonly = 0xFE1E, Refanytype = 0xFE1D, Refanyval = 0x00C2, Rem = 0x005D, Rem_Un = 0x005E, Ret = 0x002A, Rethrow = 0xFE1A, Shl = 0x0062, Shr = 0x0063, Shr_Un = 0x0064, Sizeof = 0xFE1C, Starg = 0xFE0B, Starg_S = 0x0010, Stelem = 0x00A4, Stelem_I = 0x009B, Stelem_I1 = 0x009C, Stelem_I2 = 0x009D, Stelem_I4 = 0x009E, Stelem_I8 = 0x009F, Stelem_R4 = 0x00A0, Stelem_R8 = 0x00A1, Stelem_Ref = 0x00A2, Stfld = 0x007D, Stind_I = 0x00DF, Stind_I1 = 0x0052, Stind_I2 = 0x0053, Stind_I4 = 0x0054, Stind_I8 = 0x0055, Stind_R4 = 0x0056, Stind_R8 = 0x0057, Stind_Ref = 0x0051, Stloc = 0xFE0E, Stloc_0 = 0x000A, Stloc_1 = 0x000B, Stloc_2 = 0x000C, Stloc_3 = 0x000D, Stloc_S = 0x0013, Stobj = 0x0081, Stsfld = 0x0080, Sub = 0x0059, Sub_Ovf = 0x00DA, Sub_Ovf_Un = 0x00DB, Switch = 0x0045, Tailcall = 0xFE14, Throw = 0x007A, Unaligned = 0xFE12, Unbox = 0x0079, Unbox_Any = 0x00A5, Volatile = 0xFE13, Xor = 0x0061, #pragma warning restore } public static partial class Extensions { /// /// Converts a to an /// /// The code /// A or null if it's invalid public static OpCode ToOpCode(this Code code) { int hi = (ushort)code >> 8; int lo = (byte)code; if (hi == 0) return OpCodes.OneByteOpCodes[lo]; if (hi == 0xFE) return OpCodes.TwoByteOpCodes[lo]; if (code == Code.UNKNOWN1) return OpCodes.UNKNOWN1; if (code == Code.UNKNOWN2) return OpCodes.UNKNOWN2; return null; } } } dnlib-2.1_VS2010/src/DotNet/Emit/DynamicMethodBodyReader.cs000066400000000000000000000426551325033663500233000ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using SR = System.Reflection; using System.Reflection.Emit; using System.IO; using dnlib.DotNet.MD; using dnlib.IO; namespace dnlib.DotNet.Emit { /// /// Reads code from a DynamicMethod /// public class DynamicMethodBodyReader : MethodBodyReaderBase, ISignatureReaderHelper { static readonly ReflectionFieldInfo rtdmOwnerFieldInfo = new ReflectionFieldInfo("m_owner"); static readonly ReflectionFieldInfo dmResolverFieldInfo = new ReflectionFieldInfo("m_resolver"); static readonly ReflectionFieldInfo rslvCodeFieldInfo = new ReflectionFieldInfo("m_code"); static readonly ReflectionFieldInfo rslvDynamicScopeFieldInfo = new ReflectionFieldInfo("m_scope"); static readonly ReflectionFieldInfo rslvMethodFieldInfo = new ReflectionFieldInfo("m_method"); static readonly ReflectionFieldInfo rslvLocalsFieldInfo = new ReflectionFieldInfo("m_localSignature"); static readonly ReflectionFieldInfo rslvMaxStackFieldInfo = new ReflectionFieldInfo("m_stackSize"); static readonly ReflectionFieldInfo rslvExceptionsFieldInfo = new ReflectionFieldInfo("m_exceptions"); static readonly ReflectionFieldInfo rslvExceptionHeaderFieldInfo = new ReflectionFieldInfo("m_exceptionHeader"); static readonly ReflectionFieldInfo scopeTokensFieldInfo = new ReflectionFieldInfo("m_tokens"); static readonly ReflectionFieldInfo gfiFieldHandleFieldInfo = new ReflectionFieldInfo("m_field", "m_fieldHandle"); static readonly ReflectionFieldInfo gfiContextFieldInfo = new ReflectionFieldInfo("m_context"); static readonly ReflectionFieldInfo gmiMethodHandleFieldInfo = new ReflectionFieldInfo("m_method", "m_methodHandle"); static readonly ReflectionFieldInfo gmiContextFieldInfo = new ReflectionFieldInfo("m_context"); static readonly ReflectionFieldInfo ehCatchAddrFieldInfo = new ReflectionFieldInfo("m_catchAddr"); static readonly ReflectionFieldInfo ehCatchClassFieldInfo = new ReflectionFieldInfo("m_catchClass"); static readonly ReflectionFieldInfo ehCatchEndAddrFieldInfo = new ReflectionFieldInfo("m_catchEndAddr"); static readonly ReflectionFieldInfo ehCurrentCatchFieldInfo = new ReflectionFieldInfo("m_currentCatch"); static readonly ReflectionFieldInfo ehTypeFieldInfo = new ReflectionFieldInfo("m_type"); static readonly ReflectionFieldInfo ehStartAddrFieldInfo = new ReflectionFieldInfo("m_startAddr"); static readonly ReflectionFieldInfo ehEndAddrFieldInfo = new ReflectionFieldInfo("m_endAddr"); static readonly ReflectionFieldInfo ehEndFinallyFieldInfo = new ReflectionFieldInfo("m_endFinally"); static readonly ReflectionFieldInfo vamMethodFieldInfo = new ReflectionFieldInfo("m_method"); static readonly ReflectionFieldInfo vamDynamicMethodFieldInfo = new ReflectionFieldInfo("m_dynamicMethod"); readonly ModuleDef module; readonly Importer importer; readonly GenericParamContext gpContext; readonly MethodDef method; readonly int codeSize; readonly int maxStack; readonly List tokens; readonly IList ehInfos; readonly byte[] ehHeader; readonly string methodName; class ReflectionFieldInfo { SR.FieldInfo fieldInfo; readonly string fieldName1; readonly string fieldName2; public ReflectionFieldInfo(string fieldName) { this.fieldName1 = fieldName; } public ReflectionFieldInfo(string fieldName1, string fieldName2) { this.fieldName1 = fieldName1; this.fieldName2 = fieldName2; } public object Read(object instance) { if (fieldInfo == null) InitializeField(instance.GetType()); if (fieldInfo == null) throw new Exception(string.Format("Couldn't find field '{0}' or '{1}'", fieldName1, fieldName2)); return fieldInfo.GetValue(instance); } public bool Exists(object instance) { InitializeField(instance.GetType()); return fieldInfo != null; } void InitializeField(Type type) { if (fieldInfo != null) return; var flags = SR.BindingFlags.Instance | SR.BindingFlags.Public | SR.BindingFlags.NonPublic; fieldInfo = type.GetField(fieldName1, flags); if (fieldInfo == null && fieldName2 != null) fieldInfo = type.GetField(fieldName2, flags); } } /// /// Constructor /// /// Module that will own the method body /// This can be one of several supported types: the delegate instance /// created by DynamicMethod.CreateDelegate(), a DynamicMethod instance, a RTDynamicMethod /// instance or a DynamicResolver instance. public DynamicMethodBodyReader(ModuleDef module, object obj) : this(module, obj, new GenericParamContext()) { } /// /// Constructor /// /// Module that will own the method body /// This can be one of several supported types: the delegate instance /// created by DynamicMethod.CreateDelegate(), a DynamicMethod instance, a RTDynamicMethod /// instance or a DynamicResolver instance. /// Generic parameter context public DynamicMethodBodyReader(ModuleDef module, object obj, GenericParamContext gpContext) { this.module = module; this.importer = new Importer(module, ImporterOptions.TryToUseDefs, gpContext); this.gpContext = gpContext; this.methodName = null; if (obj == null) throw new ArgumentNullException("obj"); var del = obj as Delegate; if (del != null) { obj = del.Method; if (obj == null) throw new Exception("Delegate.Method == null"); } if (obj.GetType().ToString() == "System.Reflection.Emit.DynamicMethod+RTDynamicMethod") { obj = rtdmOwnerFieldInfo.Read(obj) as DynamicMethod; if (obj == null) throw new Exception("RTDynamicMethod.m_owner is null or invalid"); } if (obj is DynamicMethod) { methodName = ((DynamicMethod)obj).Name; obj = dmResolverFieldInfo.Read(obj); if (obj == null) throw new Exception("No resolver found"); } if (obj.GetType().ToString() != "System.Reflection.Emit.DynamicResolver") throw new Exception("Couldn't find DynamicResolver"); var code = rslvCodeFieldInfo.Read(obj) as byte[]; if (code == null) throw new Exception("No code"); codeSize = code.Length; var delMethod = rslvMethodFieldInfo.Read(obj) as SR.MethodBase; if (delMethod == null) throw new Exception("No method"); maxStack = (int)rslvMaxStackFieldInfo.Read(obj); var scope = rslvDynamicScopeFieldInfo.Read(obj); if (scope == null) throw new Exception("No scope"); var tokensList = scopeTokensFieldInfo.Read(scope) as System.Collections.IList; if (tokensList == null) throw new Exception("No tokens"); tokens = new List(tokensList.Count); for (int i = 0; i < tokensList.Count; i++) tokens.Add(tokensList[i]); ehInfos = (IList)rslvExceptionsFieldInfo.Read(obj); ehHeader = rslvExceptionHeaderFieldInfo.Read(obj) as byte[]; UpdateLocals(rslvLocalsFieldInfo.Read(obj) as byte[]); this.reader = MemoryImageStream.Create(code); this.method = CreateMethodDef(delMethod); this.parameters = this.method.Parameters; } class ExceptionInfo { public int[] CatchAddr; public Type[] CatchClass; public int[] CatchEndAddr; public int CurrentCatch; public int[] Type; public int StartAddr; public int EndAddr; public int EndFinally; } static List CreateExceptionInfos(IList ehInfos) { if (ehInfos == null) return new List(); var infos = new List(ehInfos.Count); foreach (var ehInfo in ehInfos) { var eh = new ExceptionInfo { CatchAddr = (int[])ehCatchAddrFieldInfo.Read(ehInfo), CatchClass = (Type[])ehCatchClassFieldInfo.Read(ehInfo), CatchEndAddr = (int[])ehCatchEndAddrFieldInfo.Read(ehInfo), CurrentCatch = (int)ehCurrentCatchFieldInfo.Read(ehInfo), Type = (int[])ehTypeFieldInfo.Read(ehInfo), StartAddr = (int)ehStartAddrFieldInfo.Read(ehInfo), EndAddr = (int)ehEndAddrFieldInfo.Read(ehInfo), EndFinally = (int)ehEndFinallyFieldInfo.Read(ehInfo), }; infos.Add(eh); } return infos; } void UpdateLocals(byte[] localsSig) { if (localsSig == null || localsSig.Length == 0) return; var sig = SignatureReader.ReadSig(this, module.CorLibTypes, localsSig, gpContext) as LocalSig; if (sig == null) return; foreach (var local in sig.Locals) locals.Add(new Local(local)); } MethodDef CreateMethodDef(SR.MethodBase delMethod) { bool isStatic = true; var method = new MethodDefUser(); var retType = GetReturnType(delMethod); var pms = GetParameters(delMethod); if (isStatic) method.Signature = MethodSig.CreateStatic(retType, pms.ToArray()); else method.Signature = MethodSig.CreateInstance(retType, pms.ToArray()); method.Parameters.UpdateParameterTypes(); method.ImplAttributes = MethodImplAttributes.IL; method.Attributes = MethodAttributes.PrivateScope; if (isStatic) method.Attributes |= MethodAttributes.Static; return module.UpdateRowId(method); } TypeSig GetReturnType(SR.MethodBase mb) { var mi = mb as SR.MethodInfo; if (mi != null) return importer.ImportAsTypeSig(mi.ReturnType); return module.CorLibTypes.Void; } List GetParameters(SR.MethodBase delMethod) { var pms = new List(); foreach (var param in delMethod.GetParameters()) pms.Add(importer.ImportAsTypeSig(param.ParameterType)); return pms; } /// /// Reads the code /// /// public bool Read() { ReadInstructionsNumBytes((uint)codeSize); CreateExceptionHandlers(); return true; } void CreateExceptionHandlers() { if (ehHeader != null) { if (ehHeader.Length < 4) return; var reader = new BinaryReader(new MemoryStream(ehHeader)); byte b = reader.ReadByte(); if ((b & 0x40) == 0) { // DynamicResolver only checks bit 6 // Calculate num ehs exactly the same way that DynamicResolver does int numHandlers = (ushort)((reader.ReadByte() - 2) / 12); reader.ReadUInt16(); for (int i = 0; i < numHandlers; i++) { if (reader.BaseStream.Position + 12 > reader.BaseStream.Length) break; var eh = new ExceptionHandler(); eh.HandlerType = (ExceptionHandlerType)reader.ReadUInt16(); int offs = reader.ReadUInt16(); eh.TryStart = GetInstructionThrow((uint)offs); eh.TryEnd = GetInstruction((uint)(reader.ReadByte() + offs)); offs = reader.ReadUInt16(); eh.HandlerStart = GetInstructionThrow((uint)offs); eh.HandlerEnd = GetInstruction((uint)(reader.ReadByte() + offs)); if (eh.HandlerType == ExceptionHandlerType.Catch) eh.CatchType = ReadToken(reader.ReadUInt32()) as ITypeDefOrRef; else if (eh.HandlerType == ExceptionHandlerType.Filter) eh.FilterStart = GetInstruction(reader.ReadUInt32()); else reader.ReadUInt32(); exceptionHandlers.Add(eh); } } else { reader.BaseStream.Position--; int numHandlers = (ushort)(((reader.ReadUInt32() >> 8) - 4) / 24); for (int i = 0; i < numHandlers; i++) { if (reader.BaseStream.Position + 24 > reader.BaseStream.Length) break; var eh = new ExceptionHandler(); eh.HandlerType = (ExceptionHandlerType)reader.ReadUInt32(); var offs = reader.ReadUInt32(); eh.TryStart = GetInstructionThrow((uint)offs); eh.TryEnd = GetInstruction((uint)(reader.ReadUInt32() + offs)); offs = reader.ReadUInt32(); eh.HandlerStart = GetInstructionThrow((uint)offs); eh.HandlerEnd = GetInstruction((uint)(reader.ReadUInt32() + offs)); if (eh.HandlerType == ExceptionHandlerType.Catch) eh.CatchType = ReadToken(reader.ReadUInt32()) as ITypeDefOrRef; else if (eh.HandlerType == ExceptionHandlerType.Filter) eh.FilterStart = GetInstruction(reader.ReadUInt32()); else reader.ReadUInt32(); exceptionHandlers.Add(eh); } } } else if (ehInfos != null) { foreach (var ehInfo in CreateExceptionInfos(ehInfos)) { var tryStart = GetInstructionThrow((uint)ehInfo.StartAddr); var tryEnd = GetInstruction((uint)ehInfo.EndAddr); var endFinally = ehInfo.EndFinally < 0 ? null : GetInstruction((uint)ehInfo.EndFinally); for (int i = 0; i < ehInfo.CurrentCatch; i++) { var eh = new ExceptionHandler(); eh.HandlerType = (ExceptionHandlerType)ehInfo.Type[i]; eh.TryStart = tryStart; eh.TryEnd = eh.HandlerType == ExceptionHandlerType.Finally ? endFinally : tryEnd; eh.FilterStart = null; // not supported by DynamicMethod.ILGenerator eh.HandlerStart = GetInstructionThrow((uint)ehInfo.CatchAddr[i]); eh.HandlerEnd = GetInstruction((uint)ehInfo.CatchEndAddr[i]); eh.CatchType = importer.Import(ehInfo.CatchClass[i]); exceptionHandlers.Add(eh); } } } } /// /// Returns the created method. Must be called after . /// /// A new instance public MethodDef GetMethod() { bool initLocals = true; var cilBody = new CilBody(initLocals, instructions, exceptionHandlers, locals); cilBody.MaxStack = (ushort)Math.Min(maxStack, ushort.MaxValue); instructions = null; exceptionHandlers = null; locals = null; method.Body = cilBody; method.Name = methodName; return method; } /// protected override IField ReadInlineField(Instruction instr) { return ReadToken(reader.ReadUInt32()) as IField; } /// protected override IMethod ReadInlineMethod(Instruction instr) { return ReadToken(reader.ReadUInt32()) as IMethod; } /// protected override MethodSig ReadInlineSig(Instruction instr) { return ReadToken(reader.ReadUInt32()) as MethodSig; } /// protected override string ReadInlineString(Instruction instr) { return ReadToken(reader.ReadUInt32()) as string ?? string.Empty; } /// protected override ITokenOperand ReadInlineTok(Instruction instr) { return ReadToken(reader.ReadUInt32()) as ITokenOperand; } /// protected override ITypeDefOrRef ReadInlineType(Instruction instr) { return ReadToken(reader.ReadUInt32()) as ITypeDefOrRef; } object ReadToken(uint token) { uint rid = token & 0x00FFFFFF; switch (token >> 24) { case 0x02: return ImportType(rid); case 0x04: return ImportField(rid); case 0x06: case 0x0A: return ImportMethod(rid); case 0x11: return ImportSignature(rid); case 0x70: return Resolve(rid) as string; default: return null; } } IMethod ImportMethod(uint rid) { var obj = Resolve(rid); if (obj == null) return null; if (obj is RuntimeMethodHandle) return importer.Import(SR.MethodBase.GetMethodFromHandle((RuntimeMethodHandle)obj)); if (obj.GetType().ToString() == "System.Reflection.Emit.GenericMethodInfo") { var context = (RuntimeTypeHandle)gmiContextFieldInfo.Read(obj); var method = SR.MethodBase.GetMethodFromHandle((RuntimeMethodHandle)gmiMethodHandleFieldInfo.Read(obj), context); return importer.Import(method); } if (obj.GetType().ToString() == "System.Reflection.Emit.VarArgMethod") { var method = GetVarArgMethod(obj); if (!(method is DynamicMethod)) return importer.Import(method); obj = method; } var dm = obj as DynamicMethod; if (dm != null) throw new Exception("DynamicMethod calls another DynamicMethod"); return null; } SR.MethodInfo GetVarArgMethod(object obj) { if (vamDynamicMethodFieldInfo.Exists(obj)) { // .NET 4.0+ var method = vamMethodFieldInfo.Read(obj) as SR.MethodInfo; var dynMethod = vamDynamicMethodFieldInfo.Read(obj) as DynamicMethod; return dynMethod ?? method; } else { // .NET 2.0 // This is either a DynamicMethod or a MethodInfo return vamMethodFieldInfo.Read(obj) as SR.MethodInfo; } } IField ImportField(uint rid) { var obj = Resolve(rid); if (obj == null) return null; if (obj is RuntimeFieldHandle) return importer.Import(SR.FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)obj)); if (obj.GetType().ToString() == "System.Reflection.Emit.GenericFieldInfo") { var context = (RuntimeTypeHandle)gfiContextFieldInfo.Read(obj); var field = SR.FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)gfiFieldHandleFieldInfo.Read(obj), context); return importer.Import(field); } return null; } ITypeDefOrRef ImportType(uint rid) { var obj = Resolve(rid); if (obj is RuntimeTypeHandle) return importer.Import(Type.GetTypeFromHandle((RuntimeTypeHandle)obj)); return null; } CallingConventionSig ImportSignature(uint rid) { var sig = Resolve(rid) as byte[]; if (sig == null) return null; return SignatureReader.ReadSig(this, module.CorLibTypes, sig, gpContext); } object Resolve(uint index) { if (index >= (uint)tokens.Count) return null; return tokens[(int)index]; } ITypeDefOrRef ISignatureReaderHelper.ResolveTypeDefOrRef(uint codedToken, GenericParamContext gpContext) { uint token; if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.TypeDef: case Table.TypeRef: case Table.TypeSpec: return ImportType(rid); } return null; } TypeSig ISignatureReaderHelper.ConvertRTInternalAddress(IntPtr address) { return importer.ImportAsTypeSig(MethodTableToTypeConverter.Convert(address)); } } } dnlib-2.1_VS2010/src/DotNet/Emit/ExceptionHandler.cs000066400000000000000000000027721325033663500220420ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Emit { /// /// A CIL method exception handler /// public sealed class ExceptionHandler { /// /// First instruction of try block /// public Instruction TryStart; /// /// One instruction past the end of try block or null if it ends at the end /// of the method. /// public Instruction TryEnd; /// /// Start of filter handler or null if none. The end of filter handler is /// always . /// public Instruction FilterStart; /// /// First instruction of try handler block /// public Instruction HandlerStart; /// /// One instruction past the end of try handler block or null if it ends at the end /// of the method. /// public Instruction HandlerEnd; /// /// The catch type if is /// public ITypeDefOrRef CatchType; /// /// Type of exception handler clause /// public ExceptionHandlerType HandlerType; /// /// Default constructor /// public ExceptionHandler() { } /// /// Constructor /// /// Exception clause type public ExceptionHandler(ExceptionHandlerType handlerType) { this.HandlerType = handlerType; } } } dnlib-2.1_VS2010/src/DotNet/Emit/ExceptionHandlerType.cs000066400000000000000000000006431325033663500226770ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet.Emit { /// /// Type of exception handler. See CorHdr.h/CorExceptionFlag /// [Flags] public enum ExceptionHandlerType { /// Catch = 0x0000, /// Filter = 0x0001, /// Finally = 0x0002, /// Fault = 0x0004, /// Duplicated = 0x0008, } } dnlib-2.1_VS2010/src/DotNet/Emit/Extensions.cs000066400000000000000000000002571325033663500207410ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Emit { /// /// Extension methods /// public static partial class Extensions { } } dnlib-2.1_VS2010/src/DotNet/Emit/FlowControl.cs000066400000000000000000000006231325033663500210470ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Emit { /// /// CIL opcode flow control /// public enum FlowControl { /// Branch, /// Break, /// Call, /// Cond_Branch, /// Meta, /// Next, /// Phi, /// Return, /// Throw, } } dnlib-2.1_VS2010/src/DotNet/Emit/Instruction.cs000066400000000000000000000627071325033663500211330ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using dnlib.DotNet.Pdb; using dnlib.Threading; namespace dnlib.DotNet.Emit { /// /// A CIL instruction (opcode + operand) /// public sealed class Instruction { /// /// The opcode /// public OpCode OpCode; /// /// The opcode operand /// public object Operand; /// /// Offset of the instruction in the method body /// public uint Offset; /// /// PDB sequence point or null if none /// public SequencePoint SequencePoint; /// /// Default constructor /// public Instruction() { } /// /// Constructor /// /// Opcode public Instruction(OpCode opCode) { this.OpCode = opCode; } /// /// Constructor /// /// Opcode /// The operand public Instruction(OpCode opCode, object operand) { this.OpCode = opCode; this.Operand = operand; } /// /// Creates a new instruction with no operand /// /// The opcode /// A new instance public static Instruction Create(OpCode opCode) { if (opCode.OperandType != OperandType.InlineNone) throw new ArgumentException("Must be a no-operand opcode", "opCode"); return new Instruction(opCode); } /// /// Creates a new instruction with a operand /// /// The opcode /// The value /// A new instance public static Instruction Create(OpCode opCode, byte value) { if (opCode.Code != Code.Unaligned) throw new ArgumentException("Opcode does not have a byte operand", "opCode"); return new Instruction(opCode, value); } /// /// Creates a new instruction with a operand /// /// The opcode /// The value /// A new instance public static Instruction Create(OpCode opCode, sbyte value) { if (opCode.Code != Code.Ldc_I4_S) throw new ArgumentException("Opcode does not have a sbyte operand", "opCode"); return new Instruction(opCode, value); } /// /// Creates a new instruction with an operand /// /// The opcode /// The value /// A new instance public static Instruction Create(OpCode opCode, int value) { if (opCode.OperandType != OperandType.InlineI) throw new ArgumentException("Opcode does not have an int32 operand", "opCode"); return new Instruction(opCode, value); } /// /// Creates a new instruction with a operand /// /// The opcode /// The value /// A new instance public static Instruction Create(OpCode opCode, long value) { if (opCode.OperandType != OperandType.InlineI8) throw new ArgumentException("Opcode does not have an int64 operand", "opCode"); return new Instruction(opCode, value); } /// /// Creates a new instruction with a operand /// /// The opcode /// The value /// A new instance public static Instruction Create(OpCode opCode, float value) { if (opCode.OperandType != OperandType.ShortInlineR) throw new ArgumentException("Opcode does not have a real4 operand", "opCode"); return new Instruction(opCode, value); } /// /// Creates a new instruction with a operand /// /// The opcode /// The value /// A new instance public static Instruction Create(OpCode opCode, double value) { if (opCode.OperandType != OperandType.InlineR) throw new ArgumentException("Opcode does not have a real8 operand", "opCode"); return new Instruction(opCode, value); } /// /// Creates a new instruction with a string operand /// /// The opcode /// The string /// A new instance public static Instruction Create(OpCode opCode, string s) { if (opCode.OperandType != OperandType.InlineString) throw new ArgumentException("Opcode does not have a string operand", "opCode"); return new Instruction(opCode, s); } /// /// Creates a new instruction with an instruction target operand /// /// The opcode /// Target instruction /// A new instance public static Instruction Create(OpCode opCode, Instruction target) { if (opCode.OperandType != OperandType.ShortInlineBrTarget && opCode.OperandType != OperandType.InlineBrTarget) throw new ArgumentException("Opcode does not have an instruction operand", "opCode"); return new Instruction(opCode, target); } /// /// Creates a new instruction with an instruction target list operand /// /// The opcode /// The targets /// A new instance public static Instruction Create(OpCode opCode, IList targets) { if (opCode.OperandType != OperandType.InlineSwitch) throw new ArgumentException("Opcode does not have a targets array operand", "opCode"); return new Instruction(opCode, ThreadSafeListCreator.MakeThreadSafe(targets)); } /// /// Creates a new instruction with a type operand /// /// The opcode /// The type /// A new instance public static Instruction Create(OpCode opCode, ITypeDefOrRef type) { if (opCode.OperandType != OperandType.InlineType && opCode.OperandType != OperandType.InlineTok) throw new ArgumentException("Opcode does not have a type operand", "opCode"); return new Instruction(opCode, type); } /// /// Creates a new instruction with a type operand /// /// The opcode /// The type /// A new instance public static Instruction Create(OpCode opCode, CorLibTypeSig type) { return Create(opCode, type.TypeDefOrRef); } /// /// Creates a new instruction with a method/field operand /// /// The opcode /// The method/field /// A new instance public static Instruction Create(OpCode opCode, MemberRef mr) { if (opCode.OperandType != OperandType.InlineField && opCode.OperandType != OperandType.InlineMethod && opCode.OperandType != OperandType.InlineTok) throw new ArgumentException("Opcode does not have a field operand", "opCode"); return new Instruction(opCode, mr); } /// /// Creates a new instruction with a field operand /// /// The opcode /// The field /// A new instance public static Instruction Create(OpCode opCode, IField field) { if (opCode.OperandType != OperandType.InlineField && opCode.OperandType != OperandType.InlineTok) throw new ArgumentException("Opcode does not have a field operand", "opCode"); return new Instruction(opCode, field); } /// /// Creates a new instruction with a method operand /// /// The opcode /// The method /// A new instance public static Instruction Create(OpCode opCode, IMethod method) { if (opCode.OperandType != OperandType.InlineMethod && opCode.OperandType != OperandType.InlineTok) throw new ArgumentException("Opcode does not have a method operand", "opCode"); return new Instruction(opCode, method); } /// /// Creates a new instruction with a token operand /// /// The opcode /// The token /// A new instance public static Instruction Create(OpCode opCode, ITokenOperand token) { if (opCode.OperandType != OperandType.InlineTok) throw new ArgumentException("Opcode does not have a token operand", "opCode"); return new Instruction(opCode, token); } /// /// Creates a new instruction with a method signature operand /// /// The opcode /// The method signature /// A new instance public static Instruction Create(OpCode opCode, MethodSig methodSig) { if (opCode.OperandType != OperandType.InlineSig) throw new ArgumentException("Opcode does not have a method sig operand", "opCode"); return new Instruction(opCode, methodSig); } /// /// Creates a new instruction with a method parameter operand /// /// The opcode /// The method parameter /// A new instance public static Instruction Create(OpCode opCode, Parameter parameter) { if (opCode.OperandType != OperandType.ShortInlineVar && opCode.OperandType != OperandType.InlineVar) throw new ArgumentException("Opcode does not have a method parameter operand", "opCode"); return new Instruction(opCode, parameter); } /// /// Creates a new instruction with a method local operand /// /// The opcode /// The method local /// A new instance public static Instruction Create(OpCode opCode, Local local) { if (opCode.OperandType != OperandType.ShortInlineVar && opCode.OperandType != OperandType.InlineVar) throw new ArgumentException("Opcode does not have a method local operand", "opCode"); return new Instruction(opCode, local); } /// /// Creates a ldci4 instruction /// /// Operand value /// A new instance public static Instruction CreateLdcI4(int value) { switch (value) { case -1:return OpCodes.Ldc_I4_M1.ToInstruction(); case 0: return OpCodes.Ldc_I4_0.ToInstruction(); case 1: return OpCodes.Ldc_I4_1.ToInstruction(); case 2: return OpCodes.Ldc_I4_2.ToInstruction(); case 3: return OpCodes.Ldc_I4_3.ToInstruction(); case 4: return OpCodes.Ldc_I4_4.ToInstruction(); case 5: return OpCodes.Ldc_I4_5.ToInstruction(); case 6: return OpCodes.Ldc_I4_6.ToInstruction(); case 7: return OpCodes.Ldc_I4_7.ToInstruction(); case 8: return OpCodes.Ldc_I4_8.ToInstruction(); } if (sbyte.MinValue <= value && value <= sbyte.MaxValue) return new Instruction(OpCodes.Ldc_I4_S, (sbyte)value); return new Instruction(OpCodes.Ldc_I4, value); } /// /// Gets the size in bytes of the instruction /// /// public int GetSize() { var opCode = OpCode; switch (opCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.InlineField: case OperandType.InlineI: case OperandType.InlineMethod: case OperandType.InlineSig: case OperandType.InlineString: case OperandType.InlineTok: case OperandType.InlineType: case OperandType.ShortInlineR: return opCode.Size + 4; case OperandType.InlineI8: case OperandType.InlineR: return opCode.Size + 8; case OperandType.InlineNone: case OperandType.InlinePhi: default: return opCode.Size; case OperandType.InlineSwitch: var targets = Operand as IList; return opCode.Size + 4 + (targets == null ? 0 : targets.Count * 4); case OperandType.InlineVar: return opCode.Size + 2; case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineI: case OperandType.ShortInlineVar: return opCode.Size + 1; } } static bool IsSystemVoid(TypeSig type) { return type.RemovePinnedAndModifiers().GetElementType() == ElementType.Void; } /// /// Updates with the new stack size /// /// Current stack size public void UpdateStack(ref int stack) { UpdateStack(ref stack, false); } /// /// Updates with the new stack size /// /// Current stack size /// true if the method has a return value, /// false otherwise public void UpdateStack(ref int stack, bool methodHasReturnValue) { int pushes, pops; CalculateStackUsage(methodHasReturnValue, out pushes, out pops); if (pops == -1) stack = 0; else stack += pushes - pops; } /// /// Calculates stack usage /// /// Updated with number of stack pushes /// Updated with number of stack pops or -1 if the stack should /// be cleared. public void CalculateStackUsage(out int pushes, out int pops) { CalculateStackUsage(false, out pushes, out pops); } /// /// Calculates stack usage /// /// true if method has a return value /// Updated with number of stack pushes /// Updated with number of stack pops or -1 if the stack should /// be cleared. public void CalculateStackUsage(bool methodHasReturnValue, out int pushes, out int pops) { var opCode = OpCode; if (opCode.FlowControl == FlowControl.Call) CalculateStackUsageCall(opCode, out pushes, out pops); else CalculateStackUsageNonCall(opCode, methodHasReturnValue, out pushes, out pops); } void CalculateStackUsageCall(OpCode opCode, out int pushes, out int pops) { pushes = 0; pops = 0; // It doesn't push or pop anything. The stack should be empty when JMP is executed. if (opCode.Code == Code.Jmp) return; MethodSig sig; var op = Operand; var method = op as IMethod; if (method != null) sig = method.MethodSig; else sig = op as MethodSig; // calli instruction if (sig == null) return; bool implicitThis = sig.ImplicitThis; if (!IsSystemVoid(sig.RetType) || (opCode.Code == Code.Newobj && sig.HasThis)) pushes++; pops += sig.Params.Count; var paramsAfterSentinel = sig.ParamsAfterSentinel; if (paramsAfterSentinel != null) pops += paramsAfterSentinel.Count; if (implicitThis && opCode.Code != Code.Newobj) pops++; if (opCode.Code == Code.Calli) pops++; } void CalculateStackUsageNonCall(OpCode opCode, bool hasReturnValue, out int pushes, out int pops) { StackBehaviour stackBehavior; pushes = 0; pops = 0; stackBehavior = opCode.StackBehaviourPush; switch (stackBehavior) { case StackBehaviour.Push0: break; case StackBehaviour.Push1: case StackBehaviour.Pushi: case StackBehaviour.Pushi8: case StackBehaviour.Pushr4: case StackBehaviour.Pushr8: case StackBehaviour.Pushref: pushes++; break; case StackBehaviour.Push1_push1: pushes += 2; break; case StackBehaviour.Varpush: // only call, calli, callvirt which are handled elsewhere default: break; } stackBehavior = opCode.StackBehaviourPop; switch (stackBehavior) { case StackBehaviour.Pop0: break; case StackBehaviour.Pop1: case StackBehaviour.Popi: case StackBehaviour.Popref: pops++; break; case StackBehaviour.Pop1_pop1: case StackBehaviour.Popi_pop1: case StackBehaviour.Popi_popi: case StackBehaviour.Popi_popi8: case StackBehaviour.Popi_popr4: case StackBehaviour.Popi_popr8: case StackBehaviour.Popref_pop1: case StackBehaviour.Popref_popi: pops += 2; break; case StackBehaviour.Popi_popi_popi: case StackBehaviour.Popref_popi_popi: case StackBehaviour.Popref_popi_popi8: case StackBehaviour.Popref_popi_popr4: case StackBehaviour.Popref_popi_popr8: case StackBehaviour.Popref_popi_popref: case StackBehaviour.Popref_popi_pop1: pops += 3; break; case StackBehaviour.PopAll: pops = -1; break; case StackBehaviour.Varpop: // call, calli, callvirt, newobj (all handled elsewhere), and ret if (hasReturnValue) pops++; break; default: break; } } /// /// Checks whether it's one of the leave instructions /// public bool IsLeave() { return OpCode == OpCodes.Leave || OpCode == OpCodes.Leave_S; } /// /// Checks whether it's one of the br instructions /// public bool IsBr() { return OpCode == OpCodes.Br || OpCode == OpCodes.Br_S; } /// /// Checks whether it's one of the brfalse instructions /// public bool IsBrfalse() { return OpCode == OpCodes.Brfalse || OpCode == OpCodes.Brfalse_S; } /// /// Checks whether it's one of the brtrue instructions /// public bool IsBrtrue() { return OpCode == OpCodes.Brtrue || OpCode == OpCodes.Brtrue_S; } /// /// Checks whether it's one of the conditional branch instructions (bcc, brtrue, brfalse) /// public bool IsConditionalBranch() { switch (OpCode.Code) { case Code.Bge: case Code.Bge_S: case Code.Bge_Un: case Code.Bge_Un_S: case Code.Blt: case Code.Blt_S: case Code.Blt_Un: case Code.Blt_Un_S: case Code.Bgt: case Code.Bgt_S: case Code.Bgt_Un: case Code.Bgt_Un_S: case Code.Ble: case Code.Ble_S: case Code.Ble_Un: case Code.Ble_Un_S: case Code.Brfalse: case Code.Brfalse_S: case Code.Brtrue: case Code.Brtrue_S: case Code.Beq: case Code.Beq_S: case Code.Bne_Un: case Code.Bne_Un_S: return true; default: return false; } } /// /// Checks whether this is one of the ldc.i4 instructions /// public bool IsLdcI4() { switch (OpCode.Code) { case Code.Ldc_I4_M1: case Code.Ldc_I4_0: case Code.Ldc_I4_1: case Code.Ldc_I4_2: case Code.Ldc_I4_3: case Code.Ldc_I4_4: case Code.Ldc_I4_5: case Code.Ldc_I4_6: case Code.Ldc_I4_7: case Code.Ldc_I4_8: case Code.Ldc_I4_S: case Code.Ldc_I4: return true; default: return false; } } /// /// Returns a ldc.i4 instruction's operand /// /// The integer value /// isn't one of the /// ldc.i4 opcodes public int GetLdcI4Value() { switch (OpCode.Code) { case Code.Ldc_I4_M1:return -1; case Code.Ldc_I4_0: return 0; case Code.Ldc_I4_1: return 1; case Code.Ldc_I4_2: return 2; case Code.Ldc_I4_3: return 3; case Code.Ldc_I4_4: return 4; case Code.Ldc_I4_5: return 5; case Code.Ldc_I4_6: return 6; case Code.Ldc_I4_7: return 7; case Code.Ldc_I4_8: return 8; case Code.Ldc_I4_S: return (sbyte)Operand; case Code.Ldc_I4: return (int)Operand; default: throw new InvalidOperationException(string.Format("Not a ldc.i4 instruction: {0}", this)); } } /// /// Checks whether it's one of the ldarg instructions, but does not check /// whether it's one of the ldarga instructions. /// public bool IsLdarg() { switch (OpCode.Code) { case Code.Ldarg: case Code.Ldarg_S: case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: return true; default: return false; } } /// /// Checks whether it's one of the ldloc instructions, but does not check /// whether it's one of the ldloca instructions. /// public bool IsLdloc() { switch (OpCode.Code) { case Code.Ldloc: case Code.Ldloc_0: case Code.Ldloc_1: case Code.Ldloc_2: case Code.Ldloc_3: case Code.Ldloc_S: return true; default: return false; } } /// /// Checks whether it's one of the starg instructions /// public bool IsStarg() { switch (OpCode.Code) { case Code.Starg: case Code.Starg_S: return true; default: return false; } } /// /// Checks whether it's one of the stloc instructions /// public bool IsStloc() { switch (OpCode.Code) { case Code.Stloc: case Code.Stloc_0: case Code.Stloc_1: case Code.Stloc_2: case Code.Stloc_3: case Code.Stloc_S: return true; default: return false; } } /// /// Returns the local if it's a ldloc or stloc instruction. It does not /// return the local if it's a ldloca instruction. /// /// The locals /// The local or null if it's not a ldloc or stloc /// instruction or if the local doesn't exist. public Local GetLocal(IList locals) { int index; var code = OpCode.Code; switch (code) { case Code.Ldloc: case Code.Ldloc_S: case Code.Stloc: case Code.Stloc_S: return Operand as Local; case Code.Ldloc_0: case Code.Ldloc_1: case Code.Ldloc_2: case Code.Ldloc_3: index = code - Code.Ldloc_0; break; case Code.Stloc_0: case Code.Stloc_1: case Code.Stloc_2: case Code.Stloc_3: index = code - Code.Stloc_0; break; default: return null; } return locals.Get(index, null); } /// /// Gets the index of the instruction's parameter operand or -1 if the parameter /// is missing or if it's not an instruction with a parameter operand. /// public int GetParameterIndex() { switch (OpCode.Code) { case Code.Ldarg_0: return 0; case Code.Ldarg_1: return 1; case Code.Ldarg_2: return 2; case Code.Ldarg_3: return 3; case Code.Starg: case Code.Starg_S: case Code.Ldarga: case Code.Ldarga_S: case Code.Ldarg: case Code.Ldarg_S: var parameter = Operand as Parameter; if (parameter != null) return parameter.Index; break; } return -1; } /// /// Returns a method parameter /// /// All parameters /// A parameter or null if it doesn't exist public Parameter GetParameter(IList parameters) { return parameters.Get(GetParameterIndex(), null); } /// /// Returns an argument type /// /// Method signature /// Declaring type (only needed if it's an instance method) /// The type or null if it doesn't exist public TypeSig GetArgumentType(MethodSig methodSig, ITypeDefOrRef declaringType) { if (methodSig == null) return null; int index = GetParameterIndex(); if (index == 0 && methodSig.ImplicitThis) return declaringType.ToTypeSig(); //TODO: Should be ByRef if value type if (methodSig.ImplicitThis) index--; return methodSig.Params.Get(index, null); } /// /// Clone this instance. The and fields /// are shared by this instance and the created instance. /// public Instruction Clone() { return new Instruction { Offset = Offset, OpCode = OpCode, Operand = Operand, SequencePoint = SequencePoint, }; } /// public override string ToString() { return InstructionPrinter.ToString(this); } } static partial class Extensions { /// /// Gets the opcode or if is null /// /// this /// public static OpCode GetOpCode(this Instruction self) { return self == null ? OpCodes.UNKNOWN1 : self.OpCode; } /// /// Gets the operand or null if is null /// /// this /// public static object GetOperand(this Instruction self) { return self == null ? null : self.Operand; } /// /// Gets the offset or 0 if is null /// /// this /// public static uint GetOffset(this Instruction self) { return self == null ? 0 : self.Offset; } /// /// Gets the sequence point or null if is null /// /// this /// public static dnlib.DotNet.Pdb.SequencePoint GetSequencePoint(this Instruction self) { return self == null ? null : self.SequencePoint; } } } dnlib-2.1_VS2010/src/DotNet/Emit/InstructionPrinter.cs000066400000000000000000000105531325033663500224670ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Text; using dnlib.Threading; namespace dnlib.DotNet.Emit { /// /// Converts instructions to strings /// public static class InstructionPrinter { /// /// Converts an instruction to a string /// /// The instruction /// The result public static string ToString(Instruction instr) { if (instr == null) return string.Empty; var sb = new StringBuilder(); sb.Append(string.Format("IL_{0:X4}: ", instr.Offset)); sb.Append(instr.OpCode.Name); AddOperandString(sb, instr, " "); return sb.ToString(); } /// /// Gets the instruction's operand as a string /// /// The instruction /// The operand as a string public static string GetOperandString(Instruction instr) { var sb = new StringBuilder(); AddOperandString(sb, instr, string.Empty); return sb.ToString(); } /// /// Add an instruction's operand to /// /// Place result here /// The instruction public static void AddOperandString(StringBuilder sb, Instruction instr) { AddOperandString(sb, instr, string.Empty); } /// /// Add an instruction's operand to /// /// Place result here /// The instruction /// A string that will be added before the operand, if there's /// an operand. public static void AddOperandString(StringBuilder sb, Instruction instr, string extra) { var op = instr.Operand; switch (instr.OpCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.ShortInlineBrTarget: sb.Append(extra); AddInstructionTarget(sb, op as Instruction); break; case OperandType.InlineField: case OperandType.InlineMethod: case OperandType.InlineTok: case OperandType.InlineType: sb.Append(extra); if (op is IFullName) sb.Append((op as IFullName).FullName); else if (op != null) sb.Append(op.ToString()); else sb.Append("null"); break; case OperandType.InlineI: case OperandType.InlineI8: case OperandType.InlineR: case OperandType.ShortInlineI: case OperandType.ShortInlineR: sb.Append(string.Format("{0}{1}", extra, op)); break; case OperandType.InlineSig: sb.Append(extra); sb.Append(FullNameCreator.MethodFullName(null, (UTF8String)null, op as MethodSig, null, null, null, null)); break; case OperandType.InlineString: sb.Append(extra); EscapeString(sb, op as string, true); break; case OperandType.InlineSwitch: var targets = op as IList; if (targets == null) sb.Append("null"); else { sb.Append('('); for (int i = 0; i < targets.Count; i++) { if (i != 0) sb.Append(','); AddInstructionTarget(sb, targets.Get(i, null)); } sb.Append(')'); } break; case OperandType.InlineVar: case OperandType.ShortInlineVar: sb.Append(extra); if (op == null) sb.Append("null"); else sb.Append(op.ToString()); break; case OperandType.InlineNone: case OperandType.InlinePhi: default: break; } } static void AddInstructionTarget(StringBuilder sb, Instruction targetInstr) { if (targetInstr == null) sb.Append("null"); else sb.Append(string.Format("IL_{0:X4}", targetInstr.Offset)); } static void EscapeString(StringBuilder sb, string s, bool addQuotes) { if (s == null) { sb.Append("null"); return; } if (addQuotes) sb.Append('"'); foreach (var c in s) { if ((int)c < 0x20) { switch (c) { case '\a': sb.Append(@"\a"); break; case '\b': sb.Append(@"\b"); break; case '\f': sb.Append(@"\f"); break; case '\n': sb.Append(@"\n"); break; case '\r': sb.Append(@"\r"); break; case '\t': sb.Append(@"\t"); break; case '\v': sb.Append(@"\v"); break; default: sb.Append(string.Format(@"\u{0:X4}", (int)c)); break; } } else if (c == '\\' || c == '"') { sb.Append('\\'); sb.Append(c); } else sb.Append(c); } if (addQuotes) sb.Append('"'); } } } dnlib-2.1_VS2010/src/DotNet/Emit/InvalidMethodException.cs000066400000000000000000000021021325033663500231770ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Runtime.Serialization; namespace dnlib.DotNet.Emit { /// /// Thrown when invalid data is detected while parsing a .NET method /// [Serializable] public class InvalidMethodException : Exception { /// /// Default constructor /// public InvalidMethodException() { } /// /// Constructor /// /// Error message public InvalidMethodException(string msg) : base(msg) { } /// /// Constructor /// /// Error message /// The inner exception or null if none public InvalidMethodException(string msg, Exception innerException) : base(msg, innerException) { } /// /// Constructor /// /// /// protected InvalidMethodException(SerializationInfo info, StreamingContext context) : base(info, context) { } } } dnlib-2.1_VS2010/src/DotNet/Emit/LocalList.cs000066400000000000000000000157451325033663500205000ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Diagnostics; using dnlib.Utils; using dnlib.Threading; using dnlib.DotNet.Pdb; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet.Emit { /// /// A collection of s /// [DebuggerDisplay("Count = {Count}")] public sealed class LocalList : IListListener, ThreadSafe.IList { readonly LazyList locals; /// /// Gets the number of locals /// public int Count { get { return locals.Count; } } /// /// Gets the list of locals /// public ThreadSafe.IList Locals { get { return locals; } } /// /// Gets the N'th local /// /// The local index public Local this[int index] { get { return locals[index]; } set { locals[index] = value; } } /// /// Default constructor /// public LocalList() { this.locals = new LazyList(this); } /// /// Constructor /// /// All locals that will be owned by this instance public LocalList(IEnumerable locals) { this.locals = new LazyList(this); foreach (var local in locals.GetSafeEnumerable()) this.locals.Add(local); } /// /// Adds a new local and then returns it /// /// The local that should be added to the list /// The input is always returned public Local Add(Local local) { locals.Add(local); return local; } /// void IListListener.OnLazyAdd(int index, ref Local value) { } /// void IListListener.OnAdd(int index, Local value) { value.Index = index; } /// void IListListener.OnRemove(int index, Local value) { value.Index = -1; } /// void IListListener.OnResize(int index) { for (int i = index; i < locals.Count_NoLock(); i++) locals.Get_NoLock(i).Index = i; } /// void IListListener.OnClear() { foreach (var local in locals.GetEnumerable_NoLock()) local.Index = -1; } /// public int IndexOf(Local item) { return locals.IndexOf(item); } /// public void Insert(int index, Local item) { locals.Insert(index, item); } /// public void RemoveAt(int index) { locals.RemoveAt(index); } void ICollection.Add(Local item) { locals.Add(item); } /// public void Clear() { locals.Clear(); } /// public bool Contains(Local item) { return locals.Contains(item); } /// public void CopyTo(Local[] array, int arrayIndex) { locals.CopyTo(array, arrayIndex); } /// public bool IsReadOnly { get { return false; } } /// public bool Remove(Local item) { return locals.Remove(item); } /// public IEnumerator GetEnumerator() { return locals.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } #if THREAD_SAFE /// public int IndexOf_NoLock(Local item) { return locals.IndexOf_NoLock(item); } /// public void Insert_NoLock(int index, Local item) { locals.Insert_NoLock(index, item); } /// public void RemoveAt_NoLock(int index) { locals.RemoveAt_NoLock(index); } /// public Local Get_NoLock(int index) { return locals.Get_NoLock(index); } /// public void Set_NoLock(int index, Local value) { locals.Set_NoLock(index, value); } /// public void Add_NoLock(Local item) { locals.Add_NoLock(item); } /// public void Clear_NoLock() { locals.Clear_NoLock(); } /// public bool Contains_NoLock(Local item) { return locals.Contains_NoLock(item); } /// public void CopyTo_NoLock(Local[] array, int arrayIndex) { locals.CopyTo_NoLock(array, arrayIndex); } /// public int Count_NoLock { get { return locals.Count_NoLock; } } /// public bool IsReadOnly_NoLock { get { return locals.IsReadOnly_NoLock; } } /// public bool Remove_NoLock(Local item) { return locals.Remove_NoLock(item); } /// public IEnumerator GetEnumerator_NoLock() { return locals.GetEnumerator_NoLock(); } /// public TRetType ExecuteLocked(TArgType arg, ExecuteLockedDelegate handler) { return locals.ExecuteLocked(arg, (tsList, arg2) => handler(this, arg2)); } #endif } /// /// A method local /// public sealed class Local : IVariable { TypeSig typeSig; int index; string name; PdbLocalAttributes attributes; /// /// Gets/sets the type of the local /// public TypeSig Type { get { return typeSig; } set { typeSig = value; } } /// /// Local index /// public int Index { get { return index; } internal set { index = value; } } /// /// Gets the name. This property is obsolete, use to get/set the name stored in the PDB file. /// public string Name { get { return name; } set { name = value; } } /// /// Gets the attributes. This property is obsolete, use to get/set the attributes stored in the PDB file. /// public PdbLocalAttributes Attributes { get { return attributes; } set { attributes = value; } } internal void SetName(string name) { this.name = name; } internal void SetAttributes(PdbLocalAttributes attributes) { this.attributes = attributes; } /// /// Constructor /// /// The type public Local(TypeSig typeSig) { this.typeSig = typeSig; } /// /// Constructor /// /// The type /// Name of local public Local(TypeSig typeSig, string name) { this.typeSig = typeSig; this.name = name; } /// /// Constructor /// /// The type /// Name of local /// Index, should only be used if you don't add it to the locals list public Local(TypeSig typeSig, string name, int index) { this.typeSig = typeSig; this.name = name; this.index = index; } /// public override string ToString() { var n = name; if (string.IsNullOrEmpty(n)) return string.Format("V_{0}", Index); return n; } } } dnlib-2.1_VS2010/src/DotNet/Emit/MethodBody.cs000066400000000000000000000151241325033663500206370ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using dnlib.DotNet.Pdb; using dnlib.PE; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet.Emit { /// /// Method body base class /// public abstract class MethodBody { } /// /// A native method body /// public sealed class NativeMethodBody : MethodBody { RVA rva; /// /// Gets/sets the RVA of the native method body /// public RVA RVA { get { return rva; } set { rva = value; } } /// /// Default constructor /// public NativeMethodBody() { } /// /// Constructor /// /// RVA of method body public NativeMethodBody(RVA rva) { this.rva = rva; } } /// /// CIL (managed code) body /// public sealed class CilBody : MethodBody { bool keepOldMaxStack; bool initLocals; byte headerSize; ushort maxStack; uint localVarSigTok; readonly ThreadSafe.IList instructions; readonly ThreadSafe.IList exceptionHandlers; readonly LocalList localList; /// /// Size of a small header /// public const byte SMALL_HEADER_SIZE = 1; /// /// Gets/sets a flag indicating whether the original max stack value should be used. /// public bool KeepOldMaxStack { get { return keepOldMaxStack; } set { keepOldMaxStack = value; } } /// /// Gets/sets the init locals flag. This is only valid if the method has any locals. /// public bool InitLocals { get { return initLocals; } set { initLocals = value; } } /// /// Gets/sets the size in bytes of the method body header. The instructions immediately follow /// the header. /// public byte HeaderSize { get { return headerSize; } set { headerSize = value; } } /// /// true if it was a small body header ( is 1) /// public bool IsSmallHeader { get { return headerSize == SMALL_HEADER_SIZE; } } /// /// true if it was a big body header /// public bool IsBigHeader { get { return headerSize != SMALL_HEADER_SIZE; } } /// /// Gets/sets max stack value from the fat method header. /// public ushort MaxStack { get { return maxStack; } set { maxStack = value; } } /// /// Gets/sets the locals metadata token /// public uint LocalVarSigTok { get { return localVarSigTok; } set { localVarSigTok = value; } } /// /// true if is not empty /// public bool HasInstructions { get { return instructions.Count > 0; } } /// /// Gets the instructions /// public ThreadSafe.IList Instructions { get { return instructions; } } /// /// true if is not empty /// public bool HasExceptionHandlers { get { return exceptionHandlers.Count > 0; } } /// /// Gets the exception handlers /// public ThreadSafe.IList ExceptionHandlers { get { return exceptionHandlers; } } /// /// true if is not empty /// public bool HasVariables { get { return localList.Count > 0; } } /// /// Gets the locals /// public LocalList Variables {// Only called Variables for compat w/ older code. Locals is a better and more accurate name get { return localList; } } /// /// Gets/sets the PDB method. This is null if no PDB has been loaded or if there's /// no PDB info for this method. /// public PdbMethod PdbMethod { get { return pdbMethod; } set { pdbMethod = value; } } PdbMethod pdbMethod; /// /// true if is not null /// public bool HasPdbMethod { get { return PdbMethod != null; } } /// /// Default constructor /// public CilBody() { this.initLocals = true; this.instructions = ThreadSafeListCreator.Create(); this.exceptionHandlers = ThreadSafeListCreator.Create(); this.localList = new LocalList(); } /// /// Constructor /// /// Init locals flag /// All instructions. This instance will own the list. /// All exception handlers. This instance will own the list. /// All locals. This instance will own the locals in the list. public CilBody(bool initLocals, IList instructions, IList exceptionHandlers, IList locals) { this.initLocals = initLocals; this.instructions = ThreadSafeListCreator.MakeThreadSafe(instructions); this.exceptionHandlers = ThreadSafeListCreator.MakeThreadSafe(exceptionHandlers); this.localList = new LocalList(locals); } /// /// Shorter instructions are converted to the longer form, eg. Ldc_I4_1 is /// converted to Ldc_I4 with a 1 as the operand. /// /// All method parameters, including the hidden 'this' parameter /// if it's an instance method. Use . public void SimplifyMacros(IList parameters) { instructions.SimplifyMacros(localList, parameters); } /// /// Optimizes instructions by using the shorter form if possible. Eg. Ldc_I4 1 /// will be replaced with Ldc_I4_1. /// public void OptimizeMacros() { instructions.OptimizeMacros(); } /// /// Short branch instructions are converted to the long form, eg. Beq_S is /// converted to Beq. /// public void SimplifyBranches() { instructions.SimplifyBranches(); } /// /// Optimizes branches by using the smallest possible branch /// public void OptimizeBranches() { instructions.OptimizeBranches(); } /// /// Updates each instruction's offset /// /// Total size in bytes of all instructions public uint UpdateInstructionOffsets() { return instructions.UpdateInstructionOffsets(); } } } dnlib-2.1_VS2010/src/DotNet/Emit/MethodBodyReader.cs000066400000000000000000000503351325033663500217650ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.IO; using dnlib.IO; namespace dnlib.DotNet.Emit { /// /// Reads strings from #US heap /// public interface IStringResolver { /// /// Reads a string from the #US heap /// /// String token /// A string string ReadUserString(uint token); } /// /// Resolves instruction operands /// public interface IInstructionOperandResolver : ITokenResolver, IStringResolver { } public static partial class Extensions { /// /// Resolves a token /// /// An object /// The metadata token /// A or null if is invalid public static IMDTokenProvider ResolveToken(this IInstructionOperandResolver self, uint token) { return self.ResolveToken(token, new GenericParamContext()); } } /// /// Reads a .NET method body (header, locals, instructions, exception handlers) /// public sealed class MethodBodyReader : MethodBodyReaderBase { readonly IInstructionOperandResolver opResolver; bool hasReadHeader; byte headerSize; ushort flags; ushort maxStack; uint codeSize; uint localVarSigTok; IBinaryReader exceptionsReader; readonly GenericParamContext gpContext; /// /// Creates a CIL method body or returns an empty one if doesn't /// point to the start of a valid CIL method body. /// /// The operand resolver /// A reader positioned at the start of a .NET method body /// Use parameters from this method public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, IBinaryReader reader, MethodDef method) { return CreateCilBody(opResolver, reader, null, method.Parameters, new GenericParamContext()); } /// /// Creates a CIL method body or returns an empty one if doesn't /// point to the start of a valid CIL method body. /// /// The operand resolver /// A reader positioned at the start of a .NET method body /// Use parameters from this method /// Generic parameter context public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, IBinaryReader reader, MethodDef method, GenericParamContext gpContext) { return CreateCilBody(opResolver, reader, null, method.Parameters, gpContext); } /// /// Creates a CIL method body or returns an empty one if doesn't /// point to the start of a valid CIL method body. /// /// The operand resolver /// A reader positioned at the start of a .NET method body /// Method parameters public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, IBinaryReader reader, IList parameters) { return CreateCilBody(opResolver, reader, null, parameters, new GenericParamContext()); } /// /// Creates a CIL method body or returns an empty one if doesn't /// point to the start of a valid CIL method body. /// /// The operand resolver /// A reader positioned at the start of a .NET method body /// Method parameters /// Generic parameter context public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, IBinaryReader reader, IList parameters, GenericParamContext gpContext) { return CreateCilBody(opResolver, reader, null, parameters, gpContext); } /// /// Creates a CIL method body or returns an empty one if is not /// a valid CIL method body. /// /// The operand resolver /// All code /// Exceptions or null if all exception handlers are in /// /// Method parameters public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, byte[] code, byte[] exceptions, IList parameters) { return CreateCilBody(opResolver, MemoryImageStream.Create(code), exceptions == null ? null : MemoryImageStream.Create(exceptions), parameters, new GenericParamContext()); } /// /// Creates a CIL method body or returns an empty one if is not /// a valid CIL method body. /// /// The operand resolver /// All code /// Exceptions or null if all exception handlers are in /// /// Method parameters /// Generic parameter context public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, byte[] code, byte[] exceptions, IList parameters, GenericParamContext gpContext) { return CreateCilBody(opResolver, MemoryImageStream.Create(code), exceptions == null ? null : MemoryImageStream.Create(exceptions), parameters, gpContext); } /// /// Creates a CIL method body or returns an empty one if doesn't /// point to the start of a valid CIL method body. /// /// The operand resolver /// A reader positioned at the start of a .NET method body /// Exception handler reader or null if exceptions aren't /// present or if contains the exception handlers /// Method parameters public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, IBinaryReader codeReader, IBinaryReader ehReader, IList parameters) { return CreateCilBody(opResolver, codeReader, ehReader, parameters, new GenericParamContext()); } /// /// Creates a CIL method body or returns an empty one if doesn't /// point to the start of a valid CIL method body. /// /// The operand resolver /// A reader positioned at the start of a .NET method body /// Exception handler reader or null if exceptions aren't /// present or if contains the exception handlers /// Method parameters /// Generic parameter context public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, IBinaryReader codeReader, IBinaryReader ehReader, IList parameters, GenericParamContext gpContext) { var mbReader = new MethodBodyReader(opResolver, codeReader, ehReader, parameters, gpContext); if (!mbReader.Read()) return new CilBody(); return mbReader.CreateCilBody(); } /// /// Creates a CIL method body or returns an empty one if is not /// a valid CIL method body. /// /// The operand resolver /// All code /// Exceptions or null if all exception handlers are in /// /// Method parameters /// Method header flags, eg. 2 if tiny method /// Max stack /// Code size /// Local variable signature token or 0 if none public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, byte[] code, byte[] exceptions, IList parameters, ushort flags, ushort maxStack, uint codeSize, uint localVarSigTok) { return CreateCilBody(opResolver, code, exceptions, parameters, flags, maxStack, codeSize, localVarSigTok, new GenericParamContext()); } /// /// Creates a CIL method body or returns an empty one if is not /// a valid CIL method body. /// /// The operand resolver /// All code /// Exceptions or null if all exception handlers are in /// /// Method parameters /// Method header flags, eg. 2 if tiny method /// Max stack /// Code size /// Local variable signature token or 0 if none /// Generic parameter context public static CilBody CreateCilBody(IInstructionOperandResolver opResolver, byte[] code, byte[] exceptions, IList parameters, ushort flags, ushort maxStack, uint codeSize, uint localVarSigTok, GenericParamContext gpContext) { var codeReader = MemoryImageStream.Create(code); var ehReader = exceptions == null ? null : MemoryImageStream.Create(exceptions); var mbReader = new MethodBodyReader(opResolver, codeReader, ehReader, parameters, gpContext); mbReader.SetHeader(flags, maxStack, codeSize, localVarSigTok); if (!mbReader.Read()) return new CilBody(); return mbReader.CreateCilBody(); } /// /// Constructor /// /// The operand resolver /// A reader positioned at the start of a .NET method body /// Use parameters from this method public MethodBodyReader(IInstructionOperandResolver opResolver, IBinaryReader reader, MethodDef method) : this(opResolver, reader, null, method.Parameters, new GenericParamContext()) { } /// /// Constructor /// /// The operand resolver /// A reader positioned at the start of a .NET method body /// Use parameters from this method /// Generic parameter context public MethodBodyReader(IInstructionOperandResolver opResolver, IBinaryReader reader, MethodDef method, GenericParamContext gpContext) : this(opResolver, reader, null, method.Parameters, gpContext) { } /// /// Constructor /// /// The operand resolver /// A reader positioned at the start of a .NET method body /// Method parameters public MethodBodyReader(IInstructionOperandResolver opResolver, IBinaryReader reader, IList parameters) : this(opResolver, reader, null, parameters, new GenericParamContext()) { } /// /// Constructor /// /// The operand resolver /// A reader positioned at the start of a .NET method body /// Method parameters /// Generic parameter context public MethodBodyReader(IInstructionOperandResolver opResolver, IBinaryReader reader, IList parameters, GenericParamContext gpContext) : this(opResolver, reader, null, parameters, gpContext) { } /// /// Constructor /// /// The operand resolver /// A reader positioned at the start of a .NET method body /// Exception handler reader or null if exceptions aren't /// present or if contains the exception handlers /// Method parameters public MethodBodyReader(IInstructionOperandResolver opResolver, IBinaryReader codeReader, IBinaryReader ehReader, IList parameters) : this(opResolver, codeReader, ehReader, parameters, new GenericParamContext()) { } /// /// Constructor /// /// The operand resolver /// A reader positioned at the start of a .NET method body /// Exception handler reader or null if exceptions aren't /// present or if contains the exception handlers /// Method parameters /// Generic parameter context public MethodBodyReader(IInstructionOperandResolver opResolver, IBinaryReader codeReader, IBinaryReader ehReader, IList parameters, GenericParamContext gpContext) : base(codeReader, parameters) { this.opResolver = opResolver; this.exceptionsReader = ehReader; this.gpContext = gpContext; } /// /// Initializes the method header /// /// Header flags, eg. 2 if it's a tiny method /// Max stack /// Code size /// Local variable signature token void SetHeader(ushort flags, ushort maxStack, uint codeSize, uint localVarSigTok) { this.hasReadHeader = true; this.flags = flags; this.maxStack = maxStack; this.codeSize = codeSize; this.localVarSigTok = localVarSigTok; } /// /// Reads the method body header, locals, all instructions, and the exception handlers (if any) /// /// true if it worked, and false if something failed public bool Read() { try { if (!ReadHeader()) return false; SetLocals(ReadLocals()); ReadInstructions(); ReadExceptionHandlers(); return true; } catch (InvalidMethodException) { return false; } catch (IOException) { return false; } } /// /// Reads the method header /// bool ReadHeader() { if (hasReadHeader) return true; hasReadHeader = true; byte b = reader.ReadByte(); switch (b & 7) { case 2: case 6: // Tiny header. [7:2] = code size, max stack is 8, no locals or exception handlers flags = 2; maxStack = 8; codeSize = (uint)(b >> 2); localVarSigTok = 0; headerSize = 1; break; case 3: // Fat header. Can have locals and exception handlers flags = (ushort)((reader.ReadByte() << 8) | b); headerSize = (byte)(flags >> 12); maxStack = reader.ReadUInt16(); codeSize = reader.ReadUInt32(); localVarSigTok = reader.ReadUInt32(); // The CLR allows the code to start inside the method header. But if it does, // the CLR doesn't read any exceptions. reader.Position += -12 + headerSize * 4; if (headerSize < 3) flags &= 0xFFF7; headerSize *= 4; break; default: return false; } if (reader.Position + codeSize < reader.Position || reader.Position + codeSize > reader.Length) return false; return true; } /// /// Reads the locals /// /// All locals or null if there are none IList ReadLocals() { var standAloneSig = opResolver.ResolveToken(localVarSigTok, gpContext) as StandAloneSig; if (standAloneSig == null) return null; var localSig = standAloneSig.LocalSig; if (localSig == null) return null; return localSig.Locals; } /// /// Reads all instructions /// void ReadInstructions() { ReadInstructionsNumBytes(codeSize); } /// protected override IField ReadInlineField(Instruction instr) { return opResolver.ResolveToken(reader.ReadUInt32(), gpContext) as IField; } /// protected override IMethod ReadInlineMethod(Instruction instr) { return opResolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod; } /// protected override MethodSig ReadInlineSig(Instruction instr) { var standAloneSig = opResolver.ResolveToken(reader.ReadUInt32(), gpContext) as StandAloneSig; if (standAloneSig == null) return null; var sig = standAloneSig.MethodSig; if (sig != null) sig.OriginalToken = standAloneSig.MDToken.Raw; return sig; } /// protected override string ReadInlineString(Instruction instr) { return opResolver.ReadUserString(reader.ReadUInt32()) ?? string.Empty; } /// protected override ITokenOperand ReadInlineTok(Instruction instr) { return opResolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITokenOperand; } /// protected override ITypeDefOrRef ReadInlineType(Instruction instr) { return opResolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef; } /// /// Reads all exception handlers /// void ReadExceptionHandlers() { if ((flags & 8) == 0) return; IBinaryReader ehReader; if (exceptionsReader != null) ehReader = exceptionsReader; else { ehReader = reader; ehReader.Position = (ehReader.Position + 3) & ~3; } // Only read the first one. Any others aren't used. byte b = ehReader.ReadByte(); if ((b & 0x3F) != 1) return; // Not exception handler clauses if ((b & 0x40) != 0) ReadFatExceptionHandlers(ehReader); else ReadSmallExceptionHandlers(ehReader); } static ushort GetNumberOfExceptionHandlers(uint num) { // The CLR truncates the count so num handlers is always <= FFFFh. return (ushort)num; } void ReadFatExceptionHandlers(IBinaryReader ehReader) { ehReader.Position--; int num = GetNumberOfExceptionHandlers((ehReader.ReadUInt32() >> 8) / 24); for (int i = 0; i < num; i++) { var eh = new ExceptionHandler((ExceptionHandlerType)ehReader.ReadUInt32()); uint offs = ehReader.ReadUInt32(); eh.TryStart = GetInstruction(offs); eh.TryEnd = GetInstruction(offs + ehReader.ReadUInt32()); offs = ehReader.ReadUInt32(); eh.HandlerStart = GetInstruction(offs); eh.HandlerEnd = GetInstruction(offs + ehReader.ReadUInt32()); if (eh.HandlerType == ExceptionHandlerType.Catch) eh.CatchType = opResolver.ResolveToken(ehReader.ReadUInt32(), gpContext) as ITypeDefOrRef; else if (eh.HandlerType == ExceptionHandlerType.Filter) eh.FilterStart = GetInstruction(ehReader.ReadUInt32()); else ehReader.ReadUInt32(); Add(eh); } } void ReadSmallExceptionHandlers(IBinaryReader ehReader) { int num = GetNumberOfExceptionHandlers((uint)ehReader.ReadByte() / 12); ehReader.Position += 2; for (int i = 0; i < num; i++) { var eh = new ExceptionHandler((ExceptionHandlerType)ehReader.ReadUInt16()); uint offs = ehReader.ReadUInt16(); eh.TryStart = GetInstruction(offs); eh.TryEnd = GetInstruction(offs + ehReader.ReadByte()); offs = ehReader.ReadUInt16(); eh.HandlerStart = GetInstruction(offs); eh.HandlerEnd = GetInstruction(offs + ehReader.ReadByte()); if (eh.HandlerType == ExceptionHandlerType.Catch) eh.CatchType = opResolver.ResolveToken(ehReader.ReadUInt32(), gpContext) as ITypeDefOrRef; else if (eh.HandlerType == ExceptionHandlerType.Filter) eh.FilterStart = GetInstruction(ehReader.ReadUInt32()); else ehReader.ReadUInt32(); Add(eh); } } /// /// Creates a CIL body. Must be called after , and can only be /// called once. /// /// A new instance public CilBody CreateCilBody() { // Set init locals if it's a tiny method or if the init locals bit is set (fat header) bool initLocals = flags == 2 || (flags & 0x10) != 0; var cilBody = new CilBody(initLocals, instructions, exceptionHandlers, locals); cilBody.HeaderSize = headerSize; cilBody.MaxStack = maxStack; cilBody.LocalVarSigTok = localVarSigTok; instructions = null; exceptionHandlers = null; locals = null; return cilBody; } } } dnlib-2.1_VS2010/src/DotNet/Emit/MethodBodyReaderBase.cs000066400000000000000000000442061325033663500225600ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using dnlib.IO; using dnlib.Threading; namespace dnlib.DotNet.Emit { /// /// Method body reader base class /// public abstract class MethodBodyReaderBase { /// The method reader protected IBinaryReader reader; /// All parameters protected IList parameters; /// All locals protected IList locals = new List(); /// All instructions protected IList instructions; /// All exception handlers protected IList exceptionHandlers = new List(); uint currentOffset; /// First byte after the end of the code protected long codeEndOffs; /// Start offset of method protected long codeStartOffs; /// /// Gets all parameters /// public IList Parameters { get { return parameters; } } /// /// Gets all locals /// public IList Locals { get { return locals; } } /// /// Gets all instructions /// public IList Instructions { get { return instructions; } } /// /// Gets all exception handlers /// public IList ExceptionHandlers { get { return exceptionHandlers; } } /// /// Constructor /// protected MethodBodyReaderBase() { } /// /// Constructor /// /// The reader protected MethodBodyReaderBase(IBinaryReader reader) : this(reader, null) { } /// /// Constructor /// /// The reader /// Method parameters or null if they're not known yet protected MethodBodyReaderBase(IBinaryReader reader, IList parameters) { this.reader = reader; this.parameters = parameters; } /// /// Sets new locals /// /// A list of types of all locals or null if none protected void SetLocals(IList newLocals) { locals.Clear(); if (newLocals == null) return; foreach (var typeSig in newLocals.GetSafeEnumerable()) locals.Add(new Local(typeSig)); } /// /// Sets new locals /// /// A list of types of all locals or null if none protected void SetLocals(IList newLocals) { locals.Clear(); if (newLocals == null) return; foreach (var local in newLocals.GetSafeEnumerable()) locals.Add(new Local(local.Type)); } /// /// Reads all instructions /// /// Number of instructions to read protected void ReadInstructions(int numInstrs) { codeStartOffs = reader.Position; codeEndOffs = reader.Length; // We don't know the end pos so use the last one instructions = new List(numInstrs); currentOffset = 0; for (int i = 0; i < numInstrs && reader.Position < codeEndOffs; i++) instructions.Add(ReadOneInstruction()); FixBranches(); } /// /// Reads all instructions /// /// Size of code protected void ReadInstructionsNumBytes(uint codeSize) { codeStartOffs = reader.Position; codeEndOffs = reader.Position + codeSize; if (codeEndOffs < codeStartOffs || codeEndOffs > reader.Length) throw new InvalidMethodException("Invalid code size"); instructions = new List(); //TODO: Estimate number of instructions based on codeSize currentOffset = 0; while (reader.Position < codeEndOffs) instructions.Add(ReadOneInstruction()); reader.Position = codeEndOffs; FixBranches(); } /// /// Fixes all branch instructions so their operands are set to an /// instead of an offset. /// void FixBranches() { foreach (var instr in instructions) { switch (instr.OpCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.ShortInlineBrTarget: instr.Operand = GetInstruction((uint)instr.Operand); break; case OperandType.InlineSwitch: var uintTargets = (IList)instr.Operand; var targets = new Instruction[uintTargets.Count]; for (int i = 0; i < uintTargets.Count; i++) targets[i] = GetInstruction(uintTargets[i]); instr.Operand = targets; break; } } } /// /// Finds an instruction /// /// Offset of instruction /// The instruction or null if there's no instruction at . protected Instruction GetInstruction(uint offset) { // The instructions are sorted and all Offset fields are correct. Do a binary search. int lo = 0, hi = instructions.Count - 1; while (lo <= hi && hi != -1) { int i = (lo + hi) / 2; var instr = instructions[i]; if (instr.Offset == offset) return instr; if (offset < instr.Offset) hi = i - 1; else lo = i + 1; } return null; } /// /// Finds an instruction and throws if it's not present /// /// Offset of instruction /// The instruction /// There's no instruction at /// protected Instruction GetInstructionThrow(uint offset) { var instr = GetInstruction(offset); if (instr != null) return instr; throw new InvalidOperationException(string.Format("There's no instruction @ {0:X4}", offset)); } /// /// Reads the next instruction /// Instruction ReadOneInstruction() { var instr = new Instruction(); instr.Offset = currentOffset; instr.OpCode = ReadOpCode(); instr.Operand = ReadOperand(instr); if (instr.OpCode.Code == Code.Switch) { var targets = (IList)instr.Operand; currentOffset += (uint)(instr.OpCode.Size + 4 + 4 * targets.Count); } else currentOffset += (uint)instr.GetSize(); if (currentOffset < instr.Offset) reader.Position = codeEndOffs; return instr; } /// /// Reads the next OpCode from the current position /// OpCode ReadOpCode() { var op = reader.ReadByte(); if (op != 0xFE) return OpCodes.OneByteOpCodes[op]; return OpCodes.TwoByteOpCodes[reader.ReadByte()]; } /// /// Reads the instruction operand (if any) /// /// The instruction object ReadOperand(Instruction instr) { switch (instr.OpCode.OperandType) { case OperandType.InlineBrTarget: return ReadInlineBrTarget(instr); case OperandType.InlineField: return ReadInlineField(instr); case OperandType.InlineI: return ReadInlineI(instr); case OperandType.InlineI8: return ReadInlineI8(instr); case OperandType.InlineMethod: return ReadInlineMethod(instr); case OperandType.InlineNone: return ReadInlineNone(instr); case OperandType.InlinePhi: return ReadInlinePhi(instr); case OperandType.InlineR: return ReadInlineR(instr); case OperandType.InlineSig: return ReadInlineSig(instr); case OperandType.InlineString: return ReadInlineString(instr); case OperandType.InlineSwitch: return ReadInlineSwitch(instr); case OperandType.InlineTok: return ReadInlineTok(instr); case OperandType.InlineType: return ReadInlineType(instr); case OperandType.InlineVar: return ReadInlineVar(instr); case OperandType.ShortInlineBrTarget: return ReadShortInlineBrTarget(instr); case OperandType.ShortInlineI: return ReadShortInlineI(instr); case OperandType.ShortInlineR: return ReadShortInlineR(instr); case OperandType.ShortInlineVar: return ReadShortInlineVar(instr); default: throw new InvalidOperationException("Invalid OpCode.OperandType"); } } /// /// Reads a operand /// /// The current instruction /// The operand protected virtual uint ReadInlineBrTarget(Instruction instr) { return instr.Offset + (uint)instr.GetSize() + reader.ReadUInt32(); } /// /// Reads a operand /// /// The current instruction /// The operand protected abstract IField ReadInlineField(Instruction instr); /// /// Reads a operand /// /// The current instruction /// The operand protected virtual int ReadInlineI(Instruction instr) { return reader.ReadInt32(); } /// /// Reads a operand /// /// The current instruction /// The operand protected virtual long ReadInlineI8(Instruction instr) { return reader.ReadInt64(); } /// /// Reads a operand /// /// The current instruction /// The operand protected abstract IMethod ReadInlineMethod(Instruction instr); /// /// Reads a operand /// /// The current instruction /// The operand protected virtual object ReadInlineNone(Instruction instr) { return null; } /// /// Reads a operand /// /// The current instruction /// The operand protected virtual object ReadInlinePhi(Instruction instr) { return null; } /// /// Reads a operand /// /// The current instruction /// The operand protected virtual double ReadInlineR(Instruction instr) { return reader.ReadDouble(); } /// /// Reads a operand /// /// The current instruction /// The operand protected abstract MethodSig ReadInlineSig(Instruction instr); /// /// Reads a operand /// /// The current instruction /// The operand protected abstract string ReadInlineString(Instruction instr); /// /// Reads a operand /// /// The current instruction /// The operand protected virtual IList ReadInlineSwitch(Instruction instr) { var num = reader.ReadUInt32(); long offsetAfterInstr = (long)instr.Offset + (long)instr.OpCode.Size + 4L + (long)num * 4; if (offsetAfterInstr > uint.MaxValue || codeStartOffs + offsetAfterInstr > codeEndOffs) { reader.Position = codeEndOffs; return new uint[0]; } var targets = new uint[num]; uint offset = (uint)offsetAfterInstr; for (int i = 0; i < targets.Length; i++) targets[i] = offset + reader.ReadUInt32(); return targets; } /// /// Reads a operand /// /// The current instruction /// The operand protected abstract ITokenOperand ReadInlineTok(Instruction instr); /// /// Reads a operand /// /// The current instruction /// The operand protected abstract ITypeDefOrRef ReadInlineType(Instruction instr); /// /// Reads a operand /// /// The current instruction /// The operand protected virtual IVariable ReadInlineVar(Instruction instr) { if (IsArgOperandInstruction(instr)) return ReadInlineVarArg(instr); return ReadInlineVarLocal(instr); } /// /// Reads a (a parameter) operand /// /// The current instruction /// The operand protected virtual Parameter ReadInlineVarArg(Instruction instr) { return GetParameter(reader.ReadUInt16()); } /// /// Reads a (a local) operand /// /// The current instruction /// The operand protected virtual Local ReadInlineVarLocal(Instruction instr) { return GetLocal(reader.ReadUInt16()); } /// /// Reads a operand /// /// The current instruction /// The operand protected virtual uint ReadShortInlineBrTarget(Instruction instr) { return instr.Offset + (uint)instr.GetSize() + (uint)reader.ReadSByte(); } /// /// Reads a operand /// /// The current instruction /// The operand protected virtual object ReadShortInlineI(Instruction instr) { if (instr.OpCode.Code == Code.Ldc_I4_S) return reader.ReadSByte(); return reader.ReadByte(); } /// /// Reads a operand /// /// The current instruction /// The operand protected virtual float ReadShortInlineR(Instruction instr) { return reader.ReadSingle(); } /// /// Reads a operand /// /// The current instruction /// The operand protected virtual IVariable ReadShortInlineVar(Instruction instr) { if (IsArgOperandInstruction(instr)) return ReadShortInlineVarArg(instr); return ReadShortInlineVarLocal(instr); } /// /// Reads a (a parameter) operand /// /// The current instruction /// The operand protected virtual Parameter ReadShortInlineVarArg(Instruction instr) { return GetParameter(reader.ReadByte()); } /// /// Reads a (a local) operand /// /// The current instruction /// The operand protected virtual Local ReadShortInlineVarLocal(Instruction instr) { return GetLocal(reader.ReadByte()); } /// /// Returns true if it's one of the ldarg/starg instructions that have an operand /// /// The instruction to check protected static bool IsArgOperandInstruction(Instruction instr) { switch (instr.OpCode.Code) { case Code.Ldarg: case Code.Ldarg_S: case Code.Ldarga: case Code.Ldarga_S: case Code.Starg: case Code.Starg_S: return true; default: return false; } } /// /// Returns a parameter /// /// A parameter index /// A or null if is invalid protected Parameter GetParameter(int index) { return parameters.Get(index, null); } /// /// Returns a local /// /// A local index /// A or null if is invalid protected Local GetLocal(int index) { return locals.Get(index, null); } /// /// Add an exception handler if it appears valid /// /// The exception handler /// true if it was added, false otherwise protected bool Add(ExceptionHandler eh) { uint tryStart = GetOffset(eh.TryStart); uint tryEnd = GetOffset(eh.TryEnd); if (tryEnd <= tryStart) return false; uint handlerStart = GetOffset(eh.HandlerStart); uint handlerEnd = GetOffset(eh.HandlerEnd); if (handlerEnd <= handlerStart) return false; if (eh.HandlerType == ExceptionHandlerType.Filter) { if (eh.FilterStart == null) return false; if (eh.FilterStart.Offset >= handlerStart) return false; } if (handlerStart <= tryStart && tryStart < handlerEnd) return false; if (handlerStart < tryEnd && tryEnd <= handlerEnd) return false; if (tryStart <= handlerStart && handlerStart < tryEnd) return false; if (tryStart < handlerEnd && handlerEnd <= tryEnd) return false; // It's probably valid, so let's add it. exceptionHandlers.Add(eh); return true; } /// /// Gets the offset of an instruction /// /// The instruction or null if the offset is the first offset /// at the end of the method. /// The instruction offset uint GetOffset(Instruction instr) { if (instr != null) return instr.Offset; if (instructions.Count == 0) return 0; return instructions[instructions.Count - 1].Offset; } /// /// Restores a 's body with the parsed method instructions /// and exception handlers /// /// The method that gets updated with the instructions, locals, and /// exception handlers. public virtual void RestoreMethod(MethodDef method) { var body = method.Body; body.Variables.Clear(); if (locals != null) { foreach (var local in locals) body.Variables.Add(local); } body.Instructions.Clear(); if (instructions != null) { foreach (var instr in instructions) body.Instructions.Add(instr); } body.ExceptionHandlers.Clear(); if (exceptionHandlers != null) { foreach (var eh in exceptionHandlers) body.ExceptionHandlers.Add(eh); } } } } dnlib-2.1_VS2010/src/DotNet/Emit/MethodTableToTypeConverter.cs000066400000000000000000000137051325033663500240310ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Reflection; using System.Reflection.Emit; using SR = System.Reflection; using dnlib.Threading; namespace dnlib.DotNet.Emit { /// /// Converts a type address to a . The address can be found in /// RuntimeTypeHandle.Value and it's the same address you use with the WinDbg SOS command /// !dumpmt. /// static class MethodTableToTypeConverter { const string METHOD_NAME = "m"; static readonly MethodInfo setMethodBodyMethodInfo = typeof(MethodBuilder).GetMethod("SetMethodBody", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); static readonly FieldInfo localSignatureFieldInfo = typeof(ILGenerator).GetField("m_localSignature", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); static readonly FieldInfo sigDoneFieldInfo = typeof(SignatureHelper).GetField("m_sigDone", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); static readonly FieldInfo currSigFieldInfo = typeof(SignatureHelper).GetField("m_currSig", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); static readonly FieldInfo signatureFieldInfo = typeof(SignatureHelper).GetField("m_signature", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); static readonly FieldInfo ptrFieldInfo = typeof(RuntimeTypeHandle).GetField("m_ptr", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); static readonly Dictionary addrToType = new Dictionary(); static ModuleBuilder moduleBuilder; static int numNewTypes; #if THREAD_SAFE static readonly Lock theLock = Lock.Create(); #endif static MethodTableToTypeConverter() { if (ptrFieldInfo == null) { #if NETSTANDARD2_0 var asmb = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("DynAsm"), AssemblyBuilderAccess.Run); #else var asmb = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("DynAsm"), AssemblyBuilderAccess.Run); #endif moduleBuilder = asmb.DefineDynamicModule("DynMod"); } } /// /// Converts to a . /// /// Address of type /// The or null public static Type Convert(IntPtr address) { Type type; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (addrToType.TryGetValue(address, out type)) return type; type = GetTypeNET20(address) ?? GetTypeUsingTypeBuilder(address); addrToType[address] = type; return type; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } static Type GetTypeUsingTypeBuilder(IntPtr address) { if (moduleBuilder == null) return null; var tb = moduleBuilder.DefineType(GetNextTypeName()); var mb = tb.DefineMethod(METHOD_NAME, SR.MethodAttributes.Static, typeof(void), new Type[0]); try { if (setMethodBodyMethodInfo != null) return GetTypeNET45(tb, mb, address); else return GetTypeNET40(tb, mb, address); } catch { moduleBuilder = null; return null; } } // .NET 4.5 and later have the documented SetMethodBody() method. static Type GetTypeNET45(TypeBuilder tb, MethodBuilder mb, IntPtr address) { byte[] code = new byte[1] { 0x2A }; int maxStack = 8; byte[] locals = GetLocalSignature(address); setMethodBodyMethodInfo.Invoke(mb, new object[5] { code, maxStack, locals, null, null }); #if NETSTANDARD2_0 var type = tb.CreateTypeInfo(); #else var type = tb.CreateType(); #endif var createdMethod = type.GetMethod(METHOD_NAME, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); return createdMethod.GetMethodBody().LocalVariables[0].LocalType; } // This code works with .NET 4.0+ but will throw an exception if .NET 2.0 is used // ("operation could destabilize the runtime") static Type GetTypeNET40(TypeBuilder tb, MethodBuilder mb, IntPtr address) { var ilg = mb.GetILGenerator(); ilg.Emit(SR.Emit.OpCodes.Ret); // We need at least one local to make sure the SignatureHelper from ILGenerator is used. ilg.DeclareLocal(typeof(int)); var locals = GetLocalSignature(address); var sigHelper = (SignatureHelper)localSignatureFieldInfo.GetValue(ilg); sigDoneFieldInfo.SetValue(sigHelper, true); currSigFieldInfo.SetValue(sigHelper, locals.Length); signatureFieldInfo.SetValue(sigHelper, locals); #if NETSTANDARD2_0 var type = tb.CreateTypeInfo(); #else var type = tb.CreateType(); #endif var createdMethod = type.GetMethod(METHOD_NAME, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); return createdMethod.GetMethodBody().LocalVariables[0].LocalType; } // .NET 2.0 - 3.5 static Type GetTypeNET20(IntPtr address) { if (ptrFieldInfo == null) return null; object th = new RuntimeTypeHandle(); ptrFieldInfo.SetValue(th, address); return Type.GetTypeFromHandle((RuntimeTypeHandle)th); } static string GetNextTypeName() { return string.Format("Type{0}", numNewTypes++); } static byte[] GetLocalSignature(IntPtr mtAddr) { ulong mtValue = (ulong)mtAddr.ToInt64(); if (IntPtr.Size == 4) { return new byte[] { 0x07, 0x01, (byte)ElementType.Internal, (byte)mtValue, (byte)(mtValue >> 8), (byte)(mtValue >> 16), (byte)(mtValue >> 24), }; } else { return new byte[] { 0x07, 0x01, (byte)ElementType.Internal, (byte)mtValue, (byte)(mtValue >> 8), (byte)(mtValue >> 16), (byte)(mtValue >> 24), (byte)(mtValue >> 32), (byte)(mtValue >> 40), (byte)(mtValue >> 48), (byte)(mtValue >> 56), }; } } } } dnlib-2.1_VS2010/src/DotNet/Emit/MethodUtils.cs000066400000000000000000000316401325033663500210430ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using dnlib.Threading; namespace dnlib.DotNet.Emit { /// /// Instruction utility methods /// public static class MethodUtils { /// /// Shorter instructions are converted to the longer form, eg. Ldc_I4_1 is /// converted to Ldc_I4 with a 1 as the operand. /// /// All instructions /// All locals /// All method parameters, including the hidden 'this' parameter /// if it's an instance method. Use . public static void SimplifyMacros(this IList instructions, IList locals, IList parameters) { foreach (var instr in instructions.GetSafeEnumerable()) { switch (instr.OpCode.Code) { case Code.Beq_S: instr.OpCode = OpCodes.Beq; break; case Code.Bge_S: instr.OpCode = OpCodes.Bge; break; case Code.Bge_Un_S: instr.OpCode = OpCodes.Bge_Un; break; case Code.Bgt_S: instr.OpCode = OpCodes.Bgt; break; case Code.Bgt_Un_S: instr.OpCode = OpCodes.Bgt_Un; break; case Code.Ble_S: instr.OpCode = OpCodes.Ble; break; case Code.Ble_Un_S: instr.OpCode = OpCodes.Ble_Un; break; case Code.Blt_S: instr.OpCode = OpCodes.Blt; break; case Code.Blt_Un_S: instr.OpCode = OpCodes.Blt_Un; break; case Code.Bne_Un_S: instr.OpCode = OpCodes.Bne_Un; break; case Code.Br_S: instr.OpCode = OpCodes.Br; break; case Code.Brfalse_S: instr.OpCode = OpCodes.Brfalse; break; case Code.Brtrue_S: instr.OpCode = OpCodes.Brtrue; break; case Code.Ldarg_0: instr.OpCode = OpCodes.Ldarg; instr.Operand = ReadList(parameters, 0); break; case Code.Ldarg_1: instr.OpCode = OpCodes.Ldarg; instr.Operand = ReadList(parameters, 1); break; case Code.Ldarg_2: instr.OpCode = OpCodes.Ldarg; instr.Operand = ReadList(parameters, 2); break; case Code.Ldarg_3: instr.OpCode = OpCodes.Ldarg; instr.Operand = ReadList(parameters, 3); break; case Code.Ldarg_S: instr.OpCode = OpCodes.Ldarg; break; case Code.Ldarga_S: instr.OpCode = OpCodes.Ldarga; break; case Code.Ldc_I4_0: instr.OpCode = OpCodes.Ldc_I4; instr.Operand = 0; break; case Code.Ldc_I4_1: instr.OpCode = OpCodes.Ldc_I4; instr.Operand = 1; break; case Code.Ldc_I4_2: instr.OpCode = OpCodes.Ldc_I4; instr.Operand = 2; break; case Code.Ldc_I4_3: instr.OpCode = OpCodes.Ldc_I4; instr.Operand = 3; break; case Code.Ldc_I4_4: instr.OpCode = OpCodes.Ldc_I4; instr.Operand = 4; break; case Code.Ldc_I4_5: instr.OpCode = OpCodes.Ldc_I4; instr.Operand = 5; break; case Code.Ldc_I4_6: instr.OpCode = OpCodes.Ldc_I4; instr.Operand = 6; break; case Code.Ldc_I4_7: instr.OpCode = OpCodes.Ldc_I4; instr.Operand = 7; break; case Code.Ldc_I4_8: instr.OpCode = OpCodes.Ldc_I4; instr.Operand = 8; break; case Code.Ldc_I4_M1: instr.OpCode = OpCodes.Ldc_I4; instr.Operand = -1; break; case Code.Ldc_I4_S: instr.OpCode = OpCodes.Ldc_I4; instr.Operand = (int)(sbyte)instr.Operand; break; case Code.Ldloc_0: instr.OpCode = OpCodes.Ldloc; instr.Operand = ReadList(locals, 0); break; case Code.Ldloc_1: instr.OpCode = OpCodes.Ldloc; instr.Operand = ReadList(locals, 1); break; case Code.Ldloc_2: instr.OpCode = OpCodes.Ldloc; instr.Operand = ReadList(locals, 2); break; case Code.Ldloc_3: instr.OpCode = OpCodes.Ldloc; instr.Operand = ReadList(locals, 3); break; case Code.Ldloc_S: instr.OpCode = OpCodes.Ldloc; break; case Code.Ldloca_S: instr.OpCode = OpCodes.Ldloca; break; case Code.Leave_S: instr.OpCode = OpCodes.Leave; break; case Code.Starg_S: instr.OpCode = OpCodes.Starg; break; case Code.Stloc_0: instr.OpCode = OpCodes.Stloc; instr.Operand = ReadList(locals, 0); break; case Code.Stloc_1: instr.OpCode = OpCodes.Stloc; instr.Operand = ReadList(locals, 1); break; case Code.Stloc_2: instr.OpCode = OpCodes.Stloc; instr.Operand = ReadList(locals, 2); break; case Code.Stloc_3: instr.OpCode = OpCodes.Stloc; instr.Operand = ReadList(locals, 3); break; case Code.Stloc_S: instr.OpCode = OpCodes.Stloc; break; } } } static T ReadList(IList list, int index) { if (list == null) return default(T); return list.Get(index, default(T)); } /// /// Optimizes instructions by using the shorter form if possible. Eg. Ldc_I4 1 /// will be replaced with Ldc_I4_1. /// /// All instructions public static void OptimizeMacros(this IList instructions) { foreach (var instr in instructions.GetSafeEnumerable()) { Parameter arg; Local local; switch (instr.OpCode.Code) { case Code.Ldarg: case Code.Ldarg_S: arg = instr.Operand as Parameter; if (arg == null) break; if (arg.Index == 0) { instr.OpCode = OpCodes.Ldarg_0; instr.Operand = null; } else if (arg.Index == 1) { instr.OpCode = OpCodes.Ldarg_1; instr.Operand = null; } else if (arg.Index == 2) { instr.OpCode = OpCodes.Ldarg_2; instr.Operand = null; } else if (arg.Index == 3) { instr.OpCode = OpCodes.Ldarg_3; instr.Operand = null; } else if (byte.MinValue <= arg.Index && arg.Index <= byte.MaxValue) instr.OpCode = OpCodes.Ldarg_S; break; case Code.Ldarga: arg = instr.Operand as Parameter; if (arg == null) break; if (byte.MinValue <= arg.Index && arg.Index <= byte.MaxValue) instr.OpCode = OpCodes.Ldarga_S; break; case Code.Ldc_I4: case Code.Ldc_I4_S: int i4; if (instr.Operand is int) i4 = (int)instr.Operand; else if (instr.Operand is sbyte) i4 = (sbyte)instr.Operand; else break; switch (i4) { case 0: instr.OpCode = OpCodes.Ldc_I4_0; instr.Operand = null; break; case 1: instr.OpCode = OpCodes.Ldc_I4_1; instr.Operand = null; break; case 2: instr.OpCode = OpCodes.Ldc_I4_2; instr.Operand = null; break; case 3: instr.OpCode = OpCodes.Ldc_I4_3; instr.Operand = null; break; case 4: instr.OpCode = OpCodes.Ldc_I4_4; instr.Operand = null; break; case 5: instr.OpCode = OpCodes.Ldc_I4_5; instr.Operand = null; break; case 6: instr.OpCode = OpCodes.Ldc_I4_6; instr.Operand = null; break; case 7: instr.OpCode = OpCodes.Ldc_I4_7; instr.Operand = null; break; case 8: instr.OpCode = OpCodes.Ldc_I4_8; instr.Operand = null; break; case -1: instr.OpCode = OpCodes.Ldc_I4_M1; instr.Operand = null; break; default: if (sbyte.MinValue <= i4 && i4 <= sbyte.MaxValue) { instr.OpCode = OpCodes.Ldc_I4_S; instr.Operand = (sbyte)i4; } break; } break; case Code.Ldloc: case Code.Ldloc_S: local = instr.Operand as Local; if (local == null) break; if (local.Index == 0) { instr.OpCode = OpCodes.Ldloc_0; instr.Operand = null; } else if (local.Index == 1) { instr.OpCode = OpCodes.Ldloc_1; instr.Operand = null; } else if (local.Index == 2) { instr.OpCode = OpCodes.Ldloc_2; instr.Operand = null; } else if (local.Index == 3) { instr.OpCode = OpCodes.Ldloc_3; instr.Operand = null; } else if (byte.MinValue <= local.Index && local.Index <= byte.MaxValue) instr.OpCode = OpCodes.Ldloc_S; break; case Code.Ldloca: local = instr.Operand as Local; if (local == null) break; if (byte.MinValue <= local.Index && local.Index <= byte.MaxValue) instr.OpCode = OpCodes.Ldloca_S; break; case Code.Starg: arg = instr.Operand as Parameter; if (arg == null) break; if (byte.MinValue <= arg.Index && arg.Index <= byte.MaxValue) instr.OpCode = OpCodes.Starg_S; break; case Code.Stloc: case Code.Stloc_S: local = instr.Operand as Local; if (local == null) break; if (local.Index == 0) { instr.OpCode = OpCodes.Stloc_0; instr.Operand = null; } else if (local.Index == 1) { instr.OpCode = OpCodes.Stloc_1; instr.Operand = null; } else if (local.Index == 2) { instr.OpCode = OpCodes.Stloc_2; instr.Operand = null; } else if (local.Index == 3) { instr.OpCode = OpCodes.Stloc_3; instr.Operand = null; } else if (byte.MinValue <= local.Index && local.Index <= byte.MaxValue) instr.OpCode = OpCodes.Stloc_S; break; } } OptimizeBranches(instructions); } /// /// Short branch instructions are converted to the long form, eg. Beq_S is /// converted to Beq. /// /// All instructions public static void SimplifyBranches(this IList instructions) { foreach (var instr in instructions.GetSafeEnumerable()) { switch (instr.OpCode.Code) { case Code.Beq_S: instr.OpCode = OpCodes.Beq; break; case Code.Bge_S: instr.OpCode = OpCodes.Bge; break; case Code.Bgt_S: instr.OpCode = OpCodes.Bgt; break; case Code.Ble_S: instr.OpCode = OpCodes.Ble; break; case Code.Blt_S: instr.OpCode = OpCodes.Blt; break; case Code.Bne_Un_S: instr.OpCode = OpCodes.Bne_Un; break; case Code.Bge_Un_S: instr.OpCode = OpCodes.Bge_Un; break; case Code.Bgt_Un_S: instr.OpCode = OpCodes.Bgt_Un; break; case Code.Ble_Un_S: instr.OpCode = OpCodes.Ble_Un; break; case Code.Blt_Un_S: instr.OpCode = OpCodes.Blt_Un; break; case Code.Br_S: instr.OpCode = OpCodes.Br; break; case Code.Brfalse_S:instr.OpCode = OpCodes.Brfalse; break; case Code.Brtrue_S: instr.OpCode = OpCodes.Brtrue; break; case Code.Leave_S: instr.OpCode = OpCodes.Leave; break; } } } /// /// Optimizes branches by using the smallest possible branch /// /// All instructions public static void OptimizeBranches(this IList instructions) { while (true) { UpdateInstructionOffsets(instructions); bool modified = false; foreach (var instr in instructions.GetSafeEnumerable()) { OpCode shortOpCode; switch (instr.OpCode.Code) { case Code.Beq: shortOpCode = OpCodes.Beq_S; break; case Code.Bge: shortOpCode = OpCodes.Bge_S; break; case Code.Bge_Un: shortOpCode = OpCodes.Bge_Un_S; break; case Code.Bgt: shortOpCode = OpCodes.Bgt_S; break; case Code.Bgt_Un: shortOpCode = OpCodes.Bgt_Un_S; break; case Code.Ble: shortOpCode = OpCodes.Ble_S; break; case Code.Ble_Un: shortOpCode = OpCodes.Ble_Un_S; break; case Code.Blt: shortOpCode = OpCodes.Blt_S; break; case Code.Blt_Un: shortOpCode = OpCodes.Blt_Un_S; break; case Code.Bne_Un: shortOpCode = OpCodes.Bne_Un_S; break; case Code.Br: shortOpCode = OpCodes.Br_S; break; case Code.Brfalse: shortOpCode = OpCodes.Brfalse_S; break; case Code.Brtrue: shortOpCode = OpCodes.Brtrue_S; break; case Code.Leave: shortOpCode = OpCodes.Leave_S; break; default: continue; } var targetInstr = instr.Operand as Instruction; if (targetInstr == null) continue; int afterShortInstr; if (targetInstr.Offset >= instr.Offset) { // Target is >= this instruction so use the offset after // current instruction afterShortInstr = (int)instr.Offset + instr.GetSize(); } else { // Target is < this instruction so use the offset after // the short instruction const int operandSize = 1; afterShortInstr = (int)instr.Offset + shortOpCode.Size + operandSize; } int displ = (int)targetInstr.Offset - afterShortInstr; if (sbyte.MinValue <= displ && displ <= sbyte.MaxValue) { instr.OpCode = shortOpCode; modified = true; } } if (!modified) break; } } /// /// Updates each instruction's offset /// /// All instructions /// Total size in bytes of all instructions public static uint UpdateInstructionOffsets(this IList instructions) { uint offset = 0; foreach (var instr in instructions.GetSafeEnumerable()) { instr.Offset = offset; offset += (uint)instr.GetSize(); } return offset; } } } dnlib-2.1_VS2010/src/DotNet/Emit/OpCode.cs000066400000000000000000000172611325033663500177560ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using dnlib.Threading; namespace dnlib.DotNet.Emit { /// /// A CIL opcode /// public sealed class OpCode { /// /// The opcode name /// public readonly string Name; /// /// The opcode as a enum /// public readonly Code Code; /// /// Operand type /// public readonly OperandType OperandType; /// /// Flow control info /// public readonly FlowControl FlowControl; /// /// Opcode type /// public readonly OpCodeType OpCodeType; /// /// Push stack behavior /// public readonly StackBehaviour StackBehaviourPush; // UK spelling for compatibility with Reflection /// /// Pop stack behavior /// public readonly StackBehaviour StackBehaviourPop; // UK spelling for compatibility with Reflection /// /// Gets the value which is compatible with /// public short Value { get { return (short)Code; } } /// /// Gets the size of the opcode. It's either 1 or 2 bytes. /// public int Size { get { return Code < (Code)0x100 || Code == Code.UNKNOWN1 ? 1 : 2; } } internal OpCode(string name, Code code, OperandType operandType, FlowControl flowControl, OpCodeType opCodeType, StackBehaviour push, StackBehaviour pop) { this.Name = name; this.Code = code; this.OperandType = operandType; this.FlowControl = flowControl; this.OpCodeType = opCodeType; this.StackBehaviourPush = push; this.StackBehaviourPop = pop; if (((ushort)code >> 8) == 0) OpCodes.OneByteOpCodes[(byte)code] = this; else if (((ushort)code >> 8) == 0xFE) OpCodes.TwoByteOpCodes[(byte)code] = this; } /// /// Creates a new instruction with no operand /// /// A new instance public Instruction ToInstruction() { return Instruction.Create(this); } /// /// Creates a new instruction with a operand /// /// The value /// A new instance public Instruction ToInstruction(byte value) { return Instruction.Create(this, value); } /// /// Creates a new instruction with a operand /// /// The value /// A new instance public Instruction ToInstruction(sbyte value) { return Instruction.Create(this, value); } /// /// Creates a new instruction with an operand /// /// The value /// A new instance public Instruction ToInstruction(int value) { return Instruction.Create(this, value); } /// /// Creates a new instruction with a operand /// /// The value /// A new instance public Instruction ToInstruction(long value) { return Instruction.Create(this, value); } /// /// Creates a new instruction with a operand /// /// The value /// A new instance public Instruction ToInstruction(float value) { return Instruction.Create(this, value); } /// /// Creates a new instruction with a operand /// /// The value /// A new instance public Instruction ToInstruction(double value) { return Instruction.Create(this, value); } /// /// Creates a new instruction with a string operand /// /// The string /// A new instance public Instruction ToInstruction(string s) { return Instruction.Create(this, s); } /// /// Creates a new instruction with an instruction target operand /// /// Target instruction /// A new instance public Instruction ToInstruction(Instruction target) { return Instruction.Create(this, target); } /// /// Creates a new instruction with an instruction target list operand /// /// The targets /// A new instance public Instruction ToInstruction(IList targets) { return Instruction.Create(this, ThreadSafeListCreator.MakeThreadSafe(targets)); } /// /// Creates a new instruction with a type operand /// /// The type /// A new instance public Instruction ToInstruction(ITypeDefOrRef type) { return Instruction.Create(this, type); } /// /// Creates a new instruction with a type operand /// /// The type /// A new instance public Instruction ToInstruction(CorLibTypeSig type) { return Instruction.Create(this, type.TypeDefOrRef); } /// /// Creates a new instruction with a method/field operand /// /// The method/field /// A new instance public Instruction ToInstruction(MemberRef mr) { return Instruction.Create(this, mr); } /// /// Creates a new instruction with a field operand /// /// The field /// A new instance public Instruction ToInstruction(IField field) { return Instruction.Create(this, field); } /// /// Creates a new instruction with a method operand /// /// The method /// A new instance public Instruction ToInstruction(IMethod method) { return Instruction.Create(this, method); } /// /// Creates a new instruction with a token operand /// /// The token /// A new instance public Instruction ToInstruction(ITokenOperand token) { return Instruction.Create(this, token); } /// /// Creates a new instruction with a method signature operand /// /// The method signature /// A new instance public Instruction ToInstruction(MethodSig methodSig) { return Instruction.Create(this, methodSig); } /// /// Creates a new instruction with a method parameter operand /// /// The method parameter /// A new instance public Instruction ToInstruction(Parameter parameter) { return Instruction.Create(this, parameter); } /// /// Creates a new instruction with a method local operand /// /// The method local /// A new instance public Instruction ToInstruction(Local local) { return Instruction.Create(this, local); } /// public override string ToString() { return Name; } } } dnlib-2.1_VS2010/src/DotNet/Emit/OpCodeType.cs000066400000000000000000000005171325033663500206140ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Emit { /// /// CIL opcode type /// public enum OpCodeType : byte { /// Annotation, /// Macro, /// Nternal, /// Objmodel, /// Prefix, /// Primitive, } } dnlib-2.1_VS2010/src/DotNet/Emit/OpCodes.cs000066400000000000000000001277211325033663500201440ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Emit { /// /// Contains all valid CIL opcodes /// public static class OpCodes { /// /// All one-byte opcodes /// public static readonly OpCode[] OneByteOpCodes = new OpCode[0x100]; /// /// All two-byte opcodes (first byte is 0xFE) /// public static readonly OpCode[] TwoByteOpCodes = new OpCode[0x100]; #pragma warning disable 1591 // disable XML doc warning public static readonly OpCode UNKNOWN1 = new OpCode("UNKNOWN1", Code.UNKNOWN1, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode UNKNOWN2 = new OpCode("UNKNOWN2", Code.UNKNOWN2, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Nop = new OpCode("nop", Code.Nop, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Break = new OpCode("break", Code.Break, OperandType.InlineNone, FlowControl.Break, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Ldarg_0 = new OpCode("ldarg.0", Code.Ldarg_0, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); public static readonly OpCode Ldarg_1 = new OpCode("ldarg.1", Code.Ldarg_1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); public static readonly OpCode Ldarg_2 = new OpCode("ldarg.2", Code.Ldarg_2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); public static readonly OpCode Ldarg_3 = new OpCode("ldarg.3", Code.Ldarg_3, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); public static readonly OpCode Ldloc_0 = new OpCode("ldloc.0", Code.Ldloc_0, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); public static readonly OpCode Ldloc_1 = new OpCode("ldloc.1", Code.Ldloc_1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); public static readonly OpCode Ldloc_2 = new OpCode("ldloc.2", Code.Ldloc_2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); public static readonly OpCode Ldloc_3 = new OpCode("ldloc.3", Code.Ldloc_3, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); public static readonly OpCode Stloc_0 = new OpCode("stloc.0", Code.Stloc_0, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1); public static readonly OpCode Stloc_1 = new OpCode("stloc.1", Code.Stloc_1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1); public static readonly OpCode Stloc_2 = new OpCode("stloc.2", Code.Stloc_2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1); public static readonly OpCode Stloc_3 = new OpCode("stloc.3", Code.Stloc_3, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1); public static readonly OpCode Ldarg_S = new OpCode("ldarg.s", Code.Ldarg_S, OperandType.ShortInlineVar, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); public static readonly OpCode Ldarga_S = new OpCode("ldarga.s", Code.Ldarga_S, OperandType.ShortInlineVar, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Starg_S = new OpCode("starg.s", Code.Starg_S, OperandType.ShortInlineVar, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1); public static readonly OpCode Ldloc_S = new OpCode("ldloc.s", Code.Ldloc_S, OperandType.ShortInlineVar, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push1, StackBehaviour.Pop0); public static readonly OpCode Ldloca_S = new OpCode("ldloca.s", Code.Ldloca_S, OperandType.ShortInlineVar, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Stloc_S = new OpCode("stloc.s", Code.Stloc_S, OperandType.ShortInlineVar, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1); public static readonly OpCode Ldnull = new OpCode("ldnull", Code.Ldnull, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushref, StackBehaviour.Pop0); public static readonly OpCode Ldc_I4_M1 = new OpCode("ldc.i4.m1", Code.Ldc_I4_M1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ldc_I4_0 = new OpCode("ldc.i4.0", Code.Ldc_I4_0, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ldc_I4_1 = new OpCode("ldc.i4.1", Code.Ldc_I4_1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ldc_I4_2 = new OpCode("ldc.i4.2", Code.Ldc_I4_2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ldc_I4_3 = new OpCode("ldc.i4.3", Code.Ldc_I4_3, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ldc_I4_4 = new OpCode("ldc.i4.4", Code.Ldc_I4_4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ldc_I4_5 = new OpCode("ldc.i4.5", Code.Ldc_I4_5, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ldc_I4_6 = new OpCode("ldc.i4.6", Code.Ldc_I4_6, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ldc_I4_7 = new OpCode("ldc.i4.7", Code.Ldc_I4_7, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ldc_I4_8 = new OpCode("ldc.i4.8", Code.Ldc_I4_8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ldc_I4_S = new OpCode("ldc.i4.s", Code.Ldc_I4_S, OperandType.ShortInlineI, FlowControl.Next, OpCodeType.Macro, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ldc_I4 = new OpCode("ldc.i4", Code.Ldc_I4, OperandType.InlineI, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ldc_I8 = new OpCode("ldc.i8", Code.Ldc_I8, OperandType.InlineI8, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop0); public static readonly OpCode Ldc_R4 = new OpCode("ldc.r4", Code.Ldc_R4, OperandType.ShortInlineR, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr4, StackBehaviour.Pop0); public static readonly OpCode Ldc_R8 = new OpCode("ldc.r8", Code.Ldc_R8, OperandType.InlineR, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr8, StackBehaviour.Pop0); public static readonly OpCode Dup = new OpCode("dup", Code.Dup, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1_push1, StackBehaviour.Pop1); public static readonly OpCode Pop = new OpCode("pop", Code.Pop, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop1); public static readonly OpCode Jmp = new OpCode("jmp", Code.Jmp, OperandType.InlineMethod, FlowControl.Call, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Call = new OpCode("call", Code.Call, OperandType.InlineMethod, FlowControl.Call, OpCodeType.Primitive, StackBehaviour.Varpush, StackBehaviour.Varpop); public static readonly OpCode Calli = new OpCode("calli", Code.Calli, OperandType.InlineSig, FlowControl.Call, OpCodeType.Primitive, StackBehaviour.Varpush, StackBehaviour.Varpop); public static readonly OpCode Ret = new OpCode("ret", Code.Ret, OperandType.InlineNone, FlowControl.Return, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Varpop); public static readonly OpCode Br_S = new OpCode("br.s", Code.Br_S, OperandType.ShortInlineBrTarget, FlowControl.Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Brfalse_S = new OpCode("brfalse.s", Code.Brfalse_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Popi); public static readonly OpCode Brtrue_S = new OpCode("brtrue.s", Code.Brtrue_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Popi); public static readonly OpCode Beq_S = new OpCode("beq.s", Code.Beq_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Bge_S = new OpCode("bge.s", Code.Bge_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Bgt_S = new OpCode("bgt.s", Code.Bgt_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Ble_S = new OpCode("ble.s", Code.Ble_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Blt_S = new OpCode("blt.s", Code.Blt_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Bne_Un_S = new OpCode("bne.un.s", Code.Bne_Un_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Bge_Un_S = new OpCode("bge.un.s", Code.Bge_Un_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Bgt_Un_S = new OpCode("bgt.un.s", Code.Bgt_Un_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Ble_Un_S = new OpCode("ble.un.s", Code.Ble_Un_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Blt_Un_S = new OpCode("blt.un.s", Code.Blt_Un_S, OperandType.ShortInlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Br = new OpCode("br", Code.Br, OperandType.InlineBrTarget, FlowControl.Branch, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Brfalse = new OpCode("brfalse", Code.Brfalse, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi); public static readonly OpCode Brtrue = new OpCode("brtrue", Code.Brtrue, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi); public static readonly OpCode Beq = new OpCode("beq", Code.Beq, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Bge = new OpCode("bge", Code.Bge, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Bgt = new OpCode("bgt", Code.Bgt, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Ble = new OpCode("ble", Code.Ble, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Blt = new OpCode("blt", Code.Blt, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Bne_Un = new OpCode("bne.un", Code.Bne_Un, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Bge_Un = new OpCode("bge.un", Code.Bge_Un, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Bgt_Un = new OpCode("bgt.un", Code.Bgt_Un, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Ble_Un = new OpCode("ble.un", Code.Ble_Un, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Blt_Un = new OpCode("blt.un", Code.Blt_Un, OperandType.InlineBrTarget, FlowControl.Cond_Branch, OpCodeType.Macro, StackBehaviour.Push0, StackBehaviour.Pop1_pop1); public static readonly OpCode Switch = new OpCode("switch", Code.Switch, OperandType.InlineSwitch, FlowControl.Cond_Branch, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi); public static readonly OpCode Ldind_I1 = new OpCode("ldind.i1", Code.Ldind_I1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); public static readonly OpCode Ldind_U1 = new OpCode("ldind.u1", Code.Ldind_U1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); public static readonly OpCode Ldind_I2 = new OpCode("ldind.i2", Code.Ldind_I2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); public static readonly OpCode Ldind_U2 = new OpCode("ldind.u2", Code.Ldind_U2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); public static readonly OpCode Ldind_I4 = new OpCode("ldind.i4", Code.Ldind_I4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); public static readonly OpCode Ldind_U4 = new OpCode("ldind.u4", Code.Ldind_U4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); public static readonly OpCode Ldind_I8 = new OpCode("ldind.i8", Code.Ldind_I8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Popi); public static readonly OpCode Ldind_I = new OpCode("ldind.i", Code.Ldind_I, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); public static readonly OpCode Ldind_R4 = new OpCode("ldind.r4", Code.Ldind_R4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr4, StackBehaviour.Popi); public static readonly OpCode Ldind_R8 = new OpCode("ldind.r8", Code.Ldind_R8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr8, StackBehaviour.Popi); public static readonly OpCode Ldind_Ref = new OpCode("ldind.ref", Code.Ldind_Ref, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushref, StackBehaviour.Popi); public static readonly OpCode Stind_Ref = new OpCode("stind.ref", Code.Stind_Ref, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi); public static readonly OpCode Stind_I1 = new OpCode("stind.i1", Code.Stind_I1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi); public static readonly OpCode Stind_I2 = new OpCode("stind.i2", Code.Stind_I2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi); public static readonly OpCode Stind_I4 = new OpCode("stind.i4", Code.Stind_I4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi); public static readonly OpCode Stind_I8 = new OpCode("stind.i8", Code.Stind_I8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi8); public static readonly OpCode Stind_R4 = new OpCode("stind.r4", Code.Stind_R4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popr4); public static readonly OpCode Stind_R8 = new OpCode("stind.r8", Code.Stind_R8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popr8); public static readonly OpCode Add = new OpCode("add", Code.Add, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Sub = new OpCode("sub", Code.Sub, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Mul = new OpCode("mul", Code.Mul, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Div = new OpCode("div", Code.Div, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Div_Un = new OpCode("div.un", Code.Div_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Rem = new OpCode("rem", Code.Rem, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Rem_Un = new OpCode("rem.un", Code.Rem_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode And = new OpCode("and", Code.And, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Or = new OpCode("or", Code.Or, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Xor = new OpCode("xor", Code.Xor, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Shl = new OpCode("shl", Code.Shl, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Shr = new OpCode("shr", Code.Shr, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Shr_Un = new OpCode("shr.un", Code.Shr_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Neg = new OpCode("neg", Code.Neg, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1); public static readonly OpCode Not = new OpCode("not", Code.Not, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1); public static readonly OpCode Conv_I1 = new OpCode("conv.i1", Code.Conv_I1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_I2 = new OpCode("conv.i2", Code.Conv_I2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_I4 = new OpCode("conv.i4", Code.Conv_I4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_I8 = new OpCode("conv.i8", Code.Conv_I8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop1); public static readonly OpCode Conv_R4 = new OpCode("conv.r4", Code.Conv_R4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr4, StackBehaviour.Pop1); public static readonly OpCode Conv_R8 = new OpCode("conv.r8", Code.Conv_R8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr8, StackBehaviour.Pop1); public static readonly OpCode Conv_U4 = new OpCode("conv.u4", Code.Conv_U4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_U8 = new OpCode("conv.u8", Code.Conv_U8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop1); public static readonly OpCode Callvirt = new OpCode("callvirt", Code.Callvirt, OperandType.InlineMethod, FlowControl.Call, OpCodeType.Objmodel, StackBehaviour.Varpush, StackBehaviour.Varpop); public static readonly OpCode Cpobj = new OpCode("cpobj", Code.Cpobj, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popi_popi); public static readonly OpCode Ldobj = new OpCode("ldobj", Code.Ldobj, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push1, StackBehaviour.Popi); public static readonly OpCode Ldstr = new OpCode("ldstr", Code.Ldstr, OperandType.InlineString, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushref, StackBehaviour.Pop0); public static readonly OpCode Newobj = new OpCode("newobj", Code.Newobj, OperandType.InlineMethod, FlowControl.Call, OpCodeType.Objmodel, StackBehaviour.Pushref, StackBehaviour.Varpop); public static readonly OpCode Castclass = new OpCode("castclass", Code.Castclass, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushref, StackBehaviour.Popref); public static readonly OpCode Isinst = new OpCode("isinst", Code.Isinst, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref); public static readonly OpCode Conv_R_Un = new OpCode("conv.r.un", Code.Conv_R_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr8, StackBehaviour.Pop1); public static readonly OpCode Unbox = new OpCode("unbox", Code.Unbox, OperandType.InlineType, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popref); public static readonly OpCode Throw = new OpCode("throw", Code.Throw, OperandType.InlineNone, FlowControl.Throw, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref); public static readonly OpCode Ldfld = new OpCode("ldfld", Code.Ldfld, OperandType.InlineField, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push1, StackBehaviour.Popref); public static readonly OpCode Ldflda = new OpCode("ldflda", Code.Ldflda, OperandType.InlineField, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref); public static readonly OpCode Stfld = new OpCode("stfld", Code.Stfld, OperandType.InlineField, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_pop1); public static readonly OpCode Ldsfld = new OpCode("ldsfld", Code.Ldsfld, OperandType.InlineField, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push1, StackBehaviour.Pop0); public static readonly OpCode Ldsflda = new OpCode("ldsflda", Code.Ldsflda, OperandType.InlineField, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Stsfld = new OpCode("stsfld", Code.Stsfld, OperandType.InlineField, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Pop1); public static readonly OpCode Stobj = new OpCode("stobj", Code.Stobj, OperandType.InlineType, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_pop1); public static readonly OpCode Conv_Ovf_I1_Un= new OpCode("conv.ovf.i1.un", Code.Conv_Ovf_I1_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_I2_Un= new OpCode("conv.ovf.i2.un", Code.Conv_Ovf_I2_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_I4_Un= new OpCode("conv.ovf.i4.un", Code.Conv_Ovf_I4_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_I8_Un= new OpCode("conv.ovf.i8.un", Code.Conv_Ovf_I8_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_U1_Un= new OpCode("conv.ovf.u1.un", Code.Conv_Ovf_U1_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_U2_Un= new OpCode("conv.ovf.u2.un", Code.Conv_Ovf_U2_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_U4_Un= new OpCode("conv.ovf.u4.un", Code.Conv_Ovf_U4_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_U8_Un= new OpCode("conv.ovf.u8.un", Code.Conv_Ovf_U8_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_I_Un = new OpCode("conv.ovf.i.un", Code.Conv_Ovf_I_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_U_Un = new OpCode("conv.ovf.u.un", Code.Conv_Ovf_U_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Box = new OpCode("box", Code.Box, OperandType.InlineType, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushref, StackBehaviour.Pop1); public static readonly OpCode Newarr = new OpCode("newarr", Code.Newarr, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushref, StackBehaviour.Popi); public static readonly OpCode Ldlen = new OpCode("ldlen", Code.Ldlen, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref); public static readonly OpCode Ldelema = new OpCode("ldelema", Code.Ldelema, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); public static readonly OpCode Ldelem_I1 = new OpCode("ldelem.i1", Code.Ldelem_I1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); public static readonly OpCode Ldelem_U1 = new OpCode("ldelem.u1", Code.Ldelem_U1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); public static readonly OpCode Ldelem_I2 = new OpCode("ldelem.i2", Code.Ldelem_I2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); public static readonly OpCode Ldelem_U2 = new OpCode("ldelem.u2", Code.Ldelem_U2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); public static readonly OpCode Ldelem_I4 = new OpCode("ldelem.i4", Code.Ldelem_I4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); public static readonly OpCode Ldelem_U4 = new OpCode("ldelem.u4", Code.Ldelem_U4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); public static readonly OpCode Ldelem_I8 = new OpCode("ldelem.i8", Code.Ldelem_I8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi8, StackBehaviour.Popref_popi); public static readonly OpCode Ldelem_I = new OpCode("ldelem.i", Code.Ldelem_I, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushi, StackBehaviour.Popref_popi); public static readonly OpCode Ldelem_R4 = new OpCode("ldelem.r4", Code.Ldelem_R4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushr4, StackBehaviour.Popref_popi); public static readonly OpCode Ldelem_R8 = new OpCode("ldelem.r8", Code.Ldelem_R8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushr8, StackBehaviour.Popref_popi); public static readonly OpCode Ldelem_Ref = new OpCode("ldelem.ref", Code.Ldelem_Ref, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Pushref, StackBehaviour.Popref_popi); public static readonly OpCode Stelem_I = new OpCode("stelem.i", Code.Stelem_I, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popi); public static readonly OpCode Stelem_I1 = new OpCode("stelem.i1", Code.Stelem_I1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popi); public static readonly OpCode Stelem_I2 = new OpCode("stelem.i2", Code.Stelem_I2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popi); public static readonly OpCode Stelem_I4 = new OpCode("stelem.i4", Code.Stelem_I4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popi); public static readonly OpCode Stelem_I8 = new OpCode("stelem.i8", Code.Stelem_I8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popi8); public static readonly OpCode Stelem_R4 = new OpCode("stelem.r4", Code.Stelem_R4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popr4); public static readonly OpCode Stelem_R8 = new OpCode("stelem.r8", Code.Stelem_R8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popr8); public static readonly OpCode Stelem_Ref = new OpCode("stelem.ref", Code.Stelem_Ref, OperandType.InlineNone, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_popref); public static readonly OpCode Ldelem = new OpCode("ldelem", Code.Ldelem, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push1, StackBehaviour.Popref_popi); public static readonly OpCode Stelem = new OpCode("stelem", Code.Stelem, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popref_popi_pop1); public static readonly OpCode Unbox_Any = new OpCode("unbox.any", Code.Unbox_Any, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push1, StackBehaviour.Popref); public static readonly OpCode Conv_Ovf_I1 = new OpCode("conv.ovf.i1", Code.Conv_Ovf_I1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_U1 = new OpCode("conv.ovf.u1", Code.Conv_Ovf_U1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_I2 = new OpCode("conv.ovf.i2", Code.Conv_Ovf_I2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_U2 = new OpCode("conv.ovf.u2", Code.Conv_Ovf_U2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_I4 = new OpCode("conv.ovf.i4", Code.Conv_Ovf_I4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_U4 = new OpCode("conv.ovf.u4", Code.Conv_Ovf_U4, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_I8 = new OpCode("conv.ovf.i8", Code.Conv_Ovf_I8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_U8 = new OpCode("conv.ovf.u8", Code.Conv_Ovf_U8, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi8, StackBehaviour.Pop1); public static readonly OpCode Refanyval = new OpCode("refanyval", Code.Refanyval, OperandType.InlineType, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Ckfinite = new OpCode("ckfinite", Code.Ckfinite, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushr8, StackBehaviour.Pop1); public static readonly OpCode Mkrefany = new OpCode("mkrefany", Code.Mkrefany, OperandType.InlineType, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Popi); public static readonly OpCode Ldtoken = new OpCode("ldtoken", Code.Ldtoken, OperandType.InlineTok, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Conv_U2 = new OpCode("conv.u2", Code.Conv_U2, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_U1 = new OpCode("conv.u1", Code.Conv_U1, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_I = new OpCode("conv.i", Code.Conv_I, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_I = new OpCode("conv.ovf.i", Code.Conv_Ovf_I, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Conv_Ovf_U = new OpCode("conv.ovf.u", Code.Conv_Ovf_U, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Add_Ovf = new OpCode("add.ovf", Code.Add_Ovf, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Add_Ovf_Un = new OpCode("add.ovf.un", Code.Add_Ovf_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Mul_Ovf = new OpCode("mul.ovf", Code.Mul_Ovf, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Mul_Ovf_Un = new OpCode("mul.ovf.un", Code.Mul_Ovf_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Sub_Ovf = new OpCode("sub.ovf", Code.Sub_Ovf, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Sub_Ovf_Un = new OpCode("sub.ovf.un", Code.Sub_Ovf_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop1_pop1); public static readonly OpCode Endfinally = new OpCode("endfinally", Code.Endfinally, OperandType.InlineNone, FlowControl.Return, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.PopAll); public static readonly OpCode Leave = new OpCode("leave", Code.Leave, OperandType.InlineBrTarget, FlowControl.Branch, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.PopAll); public static readonly OpCode Leave_S = new OpCode("leave.s", Code.Leave_S, OperandType.ShortInlineBrTarget, FlowControl.Branch, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.PopAll); public static readonly OpCode Stind_I = new OpCode("stind.i", Code.Stind_I, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi); public static readonly OpCode Conv_U = new OpCode("conv.u", Code.Conv_U, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Prefix7 = new OpCode("prefix7", Code.Prefix7, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Prefix6 = new OpCode("prefix6", Code.Prefix6, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Prefix5 = new OpCode("prefix5", Code.Prefix5, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Prefix4 = new OpCode("prefix4", Code.Prefix4, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Prefix3 = new OpCode("prefix3", Code.Prefix3, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Prefix2 = new OpCode("prefix2", Code.Prefix2, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Prefix1 = new OpCode("prefix1", Code.Prefix1, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Prefixref = new OpCode("prefixref", Code.Prefixref, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Nternal, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Arglist = new OpCode("arglist", Code.Arglist, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ceq = new OpCode("ceq", Code.Ceq, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1_pop1); public static readonly OpCode Cgt = new OpCode("cgt", Code.Cgt, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1_pop1); public static readonly OpCode Cgt_Un = new OpCode("cgt.un", Code.Cgt_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1_pop1); public static readonly OpCode Clt = new OpCode("clt", Code.Clt, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1_pop1); public static readonly OpCode Clt_Un = new OpCode("clt.un", Code.Clt_Un, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1_pop1); public static readonly OpCode Ldftn = new OpCode("ldftn", Code.Ldftn, OperandType.InlineMethod, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Ldvirtftn = new OpCode("ldvirtftn", Code.Ldvirtftn, OperandType.InlineMethod, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popref); public static readonly OpCode Ldarg = new OpCode("ldarg", Code.Ldarg, OperandType.InlineVar, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop0); public static readonly OpCode Ldarga = new OpCode("ldarga", Code.Ldarga, OperandType.InlineVar, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Starg = new OpCode("starg", Code.Starg, OperandType.InlineVar, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop1); public static readonly OpCode Ldloc = new OpCode("ldloc", Code.Ldloc, OperandType.InlineVar, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push1, StackBehaviour.Pop0); public static readonly OpCode Ldloca = new OpCode("ldloca", Code.Ldloca, OperandType.InlineVar, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Stloc = new OpCode("stloc", Code.Stloc, OperandType.InlineVar, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Pop1); public static readonly OpCode Localloc = new OpCode("localloc", Code.Localloc, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Popi); public static readonly OpCode Endfilter = new OpCode("endfilter", Code.Endfilter, OperandType.InlineNone, FlowControl.Return, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi); public static readonly OpCode Unaligned = new OpCode("unaligned.", Code.Unaligned, OperandType.ShortInlineI, FlowControl.Meta, OpCodeType.Prefix, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Volatile = new OpCode("volatile.", Code.Volatile, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Prefix, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Tailcall = new OpCode("tail.", Code.Tailcall, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Prefix, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Initobj = new OpCode("initobj", Code.Initobj, OperandType.InlineType, FlowControl.Next, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Popi); public static readonly OpCode Constrained = new OpCode("constrained.", Code.Constrained, OperandType.InlineType, FlowControl.Meta, OpCodeType.Prefix, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Cpblk = new OpCode("cpblk", Code.Cpblk, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi_popi); public static readonly OpCode Initblk = new OpCode("initblk", Code.Initblk, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Push0, StackBehaviour.Popi_popi_popi); // public static readonly OpCode No = new OpCode("no.", Code.No, OperandType.ShortInlineI, FlowControl.Meta, OpCodeType.Prefix, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Rethrow = new OpCode("rethrow", Code.Rethrow, OperandType.InlineNone, FlowControl.Throw, OpCodeType.Objmodel, StackBehaviour.Push0, StackBehaviour.Pop0); public static readonly OpCode Sizeof = new OpCode("sizeof", Code.Sizeof, OperandType.InlineType, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop0); public static readonly OpCode Refanytype = new OpCode("refanytype", Code.Refanytype, OperandType.InlineNone, FlowControl.Next, OpCodeType.Primitive, StackBehaviour.Pushi, StackBehaviour.Pop1); public static readonly OpCode Readonly = new OpCode("readonly.", Code.Readonly, OperandType.InlineNone, FlowControl.Meta, OpCodeType.Prefix, StackBehaviour.Push0, StackBehaviour.Pop0); #pragma warning restore static OpCodes() { // The OpCode ctor copies itself to one of these arrays. Whatever are still null // are unsupported opcodes. Set them all to UNKNOWN1 or UNKNOWN2. for (int i = 0; i < OneByteOpCodes.Length; i++) { if (OneByteOpCodes[i] == null) OneByteOpCodes[i] = UNKNOWN1; } for (int i = 0; i < TwoByteOpCodes.Length; i++) { if (TwoByteOpCodes[i] == null) TwoByteOpCodes[i] = UNKNOWN2; } } } } dnlib-2.1_VS2010/src/DotNet/Emit/OperandType.cs000066400000000000000000000035541325033663500210370ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.DotNet.MD; namespace dnlib.DotNet.Emit { /// /// CIL opcode operand type /// public enum OperandType : byte { /// 4-byte relative instruction offset InlineBrTarget, /// 4-byte field token ( or ) InlineField, /// int32 InlineI, /// int64 InlineI8, /// 4-byte method token (, /// or ) InlineMethod, /// No operand InlineNone, /// Never used InlinePhi, /// 64-bit real InlineR, /// NOT_USED_8, /// 4-byte method sig token () InlineSig, /// 4-byte string token (0x70xxxxxx) InlineString, /// 4-byte count N followed by N 4-byte relative instruction offsets InlineSwitch, /// 4-byte token (, , /// , , , /// or ) InlineTok, /// 4-byte type token (, or /// ) InlineType, /// 2-byte param/local index InlineVar, /// 1-byte relative instruction offset ShortInlineBrTarget, /// 1-byte sbyte () or byte (the rest) ShortInlineI, /// 32-bit real ShortInlineR, /// 1-byte param/local index ShortInlineVar, } } dnlib-2.1_VS2010/src/DotNet/Emit/StackBehaviour.cs000066400000000000000000000021111325033663500215030ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Emit { /// /// CIL opcode stack behavior /// public enum StackBehaviour : byte { /// Pop0, /// Pop1, /// Pop1_pop1, /// Popi, /// Popi_pop1, /// Popi_popi, /// Popi_popi8, /// Popi_popi_popi, /// Popi_popr4, /// Popi_popr8, /// Popref, /// Popref_pop1, /// Popref_popi, /// Popref_popi_popi, /// Popref_popi_popi8, /// Popref_popi_popr4, /// Popref_popi_popr8, /// Popref_popi_popref, /// Push0, /// Push1, /// Push1_push1, /// Pushi, /// Pushi8, /// Pushr4, /// Pushr8, /// Pushref, /// Varpop, /// Varpush, /// Popref_popi_pop1, /// PopAll = 0xFF, } } dnlib-2.1_VS2010/src/DotNet/EventAttributes.cs000066400000000000000000000006441325033663500210340ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// Event attributes, see CorHdr.h/CorEventAttr /// [Flags] public enum EventAttributes : ushort { /// event is special. Name describes how. SpecialName = 0x0200, /// Runtime(metadata internal APIs) should check name encoding. RTSpecialName = 0x0400, } } dnlib-2.1_VS2010/src/DotNet/EventDef.cs000066400000000000000000000317101325033663500174020ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the Event table /// public abstract class EventDef : IHasCustomAttribute, IHasSemantic, IHasCustomDebugInformation, IFullName, IMemberDef { /// /// The row id in its table /// protected uint rid; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// public MDToken MDToken { get { return new MDToken(Table.Event, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 10; } } /// public int HasSemanticTag { get { return 0; } } /// /// From column Event.EventFlags /// public EventAttributes Attributes { get { return (EventAttributes)attributes; } set { attributes = (int)value; } } /// protected int attributes; /// /// From column Event.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// From column Event.EventType /// public ITypeDefOrRef EventType { get { return eventType; } set { eventType = value; } } /// protected ITypeDefOrRef eventType; /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public int HasCustomDebugInformationTag { get { return 10; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// /// Gets/sets the adder method /// public MethodDef AddMethod { get { if (otherMethods == null) InitializeEventMethods(); return addMethod; } set { if (otherMethods == null) InitializeEventMethods(); addMethod = value; } } /// /// Gets/sets the invoker method /// public MethodDef InvokeMethod { get { if (otherMethods == null) InitializeEventMethods(); return invokeMethod; } set { if (otherMethods == null) InitializeEventMethods(); invokeMethod = value; } } /// /// Gets/sets the remover method /// public MethodDef RemoveMethod { get { if (otherMethods == null) InitializeEventMethods(); return removeMethod; } set { if (otherMethods == null) InitializeEventMethods(); removeMethod = value; } } /// /// Gets the other methods /// public ThreadSafe.IList OtherMethods { get { if (otherMethods == null) InitializeEventMethods(); return otherMethods; } } void InitializeEventMethods() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (otherMethods == null) InitializeEventMethods_NoLock(); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Initializes , , /// and . /// protected virtual void InitializeEventMethods_NoLock() { otherMethods = ThreadSafeListCreator.Create(); } /// protected MethodDef addMethod; /// protected MethodDef invokeMethod; /// protected MethodDef removeMethod; /// protected ThreadSafe.IList otherMethods; /// Reset , , , protected void ResetMethods() { otherMethods = null; } /// /// true if there are no methods attached to this event /// public bool IsEmpty { get { // The first property access initializes the other fields we access here return AddMethod == null && removeMethod == null && invokeMethod == null && otherMethods.Count == 0; } } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// /// true if is not empty /// public bool HasOtherMethods { get { return OtherMethods.Count > 0; } } /// /// Gets/sets the declaring type (owner type) /// public TypeDef DeclaringType { get { return declaringType2; } set { var currentDeclaringType = DeclaringType2; if (currentDeclaringType == value) return; if (currentDeclaringType != null) currentDeclaringType.Events.Remove(this); // Will set DeclaringType2 = null if (value != null) value.Events.Add(this); // Will set DeclaringType2 = value } } /// ITypeDefOrRef IMemberRef.DeclaringType { get { return declaringType2; } } /// /// Called by and should normally not be called by any user /// code. Use instead. Only call this if you must set the /// declaring type without inserting it in the declaring type's method list. /// public TypeDef DeclaringType2 { get { return declaringType2; } set { declaringType2 = value; } } /// protected TypeDef declaringType2; /// public ModuleDef Module { get { var dt = declaringType2; return dt == null ? null : dt.Module; } } /// /// Gets the full name of the event /// public string FullName { get { var dt = declaringType2; return FullNameCreator.EventFullName(dt == null ? null : dt.FullName, name, eventType, null, null); } } bool IIsTypeOrMethod.IsType { get { return false; } } bool IIsTypeOrMethod.IsMethod { get { return false; } } bool IMemberRef.IsField { get { return false; } } bool IMemberRef.IsTypeSpec { get { return false; } } bool IMemberRef.IsTypeRef { get { return false; } } bool IMemberRef.IsTypeDef { get { return false; } } bool IMemberRef.IsMethodSpec { get { return false; } } bool IMemberRef.IsMethodDef { get { return false; } } bool IMemberRef.IsMemberRef { get { return false; } } bool IMemberRef.IsFieldDef { get { return false; } } bool IMemberRef.IsPropertyDef { get { return false; } } bool IMemberRef.IsEventDef { get { return true; } } bool IMemberRef.IsGenericParam { get { return false; } } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyAttributes(bool set, EventAttributes 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 IsSpecialName { get { return ((EventAttributes)attributes & EventAttributes.SpecialName) != 0; } set { ModifyAttributes(value, EventAttributes.SpecialName); } } /// /// Gets/sets the bit /// public bool IsRuntimeSpecialName { get { return ((EventAttributes)attributes & EventAttributes.RTSpecialName) != 0; } set { ModifyAttributes(value, EventAttributes.RTSpecialName); } } /// public override string ToString() { return FullName; } } /// /// An Event row created by the user and not present in the original .NET file /// public class EventDefUser : EventDef { /// /// Default constructor /// public EventDefUser() { } /// /// Constructor /// /// Name public EventDefUser(UTF8String name) : this(name, null, 0) { } /// /// Constructor /// /// Name /// Type public EventDefUser(UTF8String name, ITypeDefOrRef type) : this(name, type, 0) { } /// /// Constructor /// /// Name /// Type /// Flags public EventDefUser(UTF8String name, ITypeDefOrRef type, EventAttributes flags) { this.name = name; this.eventType = type; this.attributes = (int)flags; } } /// /// Created from a row in the Event table /// sealed class EventDefMD : EventDef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.Event, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(declaringType2), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this Event row /// Row ID /// If is null /// If is invalid public EventDefMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.EventTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("Event rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; uint name; uint eventType = readerModule.TablesStream.ReadEventRow(origRid, out this.attributes, out name); this.name = readerModule.StringsStream.ReadNoNull(name); this.declaringType2 = readerModule.GetOwnerType(this); this.eventType = readerModule.ResolveTypeDefOrRef(eventType, new GenericParamContext(declaringType2)); } internal EventDefMD InitializeAll() { MemberMDInitializer.Initialize(Attributes); MemberMDInitializer.Initialize(Name); MemberMDInitializer.Initialize(EventType); MemberMDInitializer.Initialize(CustomAttributes); MemberMDInitializer.Initialize(AddMethod); MemberMDInitializer.Initialize(InvokeMethod); MemberMDInitializer.Initialize(RemoveMethod); MemberMDInitializer.Initialize(OtherMethods); MemberMDInitializer.Initialize(DeclaringType); return this; } /// protected override void InitializeEventMethods_NoLock() { ThreadSafe.IList newOtherMethods; var dt = declaringType2 as TypeDefMD; if (dt == null) newOtherMethods = ThreadSafeListCreator.Create(); else dt.InitializeEvent(this, out addMethod, out invokeMethod, out removeMethod, out newOtherMethods); otherMethods = newOtherMethods; } } } dnlib-2.1_VS2010/src/DotNet/ExportedType.cs000066400000000000000000000560161325033663500203440ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the ExportedType table /// public abstract class ExportedType : IHasCustomAttribute, IImplementation, IHasCustomDebugInformation, IType { /// /// The row id in its table /// protected uint rid; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// /// The owner module /// protected ModuleDef module; /// public MDToken MDToken { get { return new MDToken(Table.ExportedType, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 17; } } /// public int ImplementationTag { get { return 2; } } /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 17; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// public bool IsValueType { get { var td = Resolve(); return td != null && td.IsValueType; } } /// public bool IsPrimitive { get { return this.IsPrimitive(); } } /// string IType.TypeName { get { return FullNameCreator.Name(this, false, null); } } /// public UTF8String Name { get { return typeName; } set { typeName = value; } } /// public string ReflectionName { get { return FullNameCreator.Name(this, true, null); } } /// public string Namespace { get { return FullNameCreator.Namespace(this, false, null); } } /// public string ReflectionNamespace { get { return FullNameCreator.Namespace(this, true, null); } } /// public string FullName { get { return FullNameCreator.FullName(this, false, null, null); } } /// public string ReflectionFullName { get { return FullNameCreator.FullName(this, true, null, null); } } /// public string AssemblyQualifiedName { get { return FullNameCreator.AssemblyQualifiedName(this, null, null); } } /// public IAssembly DefinitionAssembly { get { return FullNameCreator.DefinitionAssembly(this); } } /// public IScope Scope { get { return FullNameCreator.Scope(this); } } /// public ITypeDefOrRef ScopeType { get { return FullNameCreator.ScopeType(this); } } /// /// Always returns false since a does not contain any /// or . /// public bool ContainsGenericParameter { get { return false; } } /// public ModuleDef Module { get { return module; } } /// bool IIsTypeOrMethod.IsMethod { get { return false; } } /// bool IIsTypeOrMethod.IsType { get { return true; } } /// int IGenericParameterProvider.NumberOfGenericParameters { get { return 0; } } /// /// From column ExportedType.Flags /// public TypeAttributes Attributes { get { return (TypeAttributes)attributes; } set { attributes = (int)value; } } /// Attributes protected int attributes; /// /// From column ExportedType.TypeDefId /// public uint TypeDefId { get { return typeDefId; } set { typeDefId = value; } } /// protected uint typeDefId; /// /// From column ExportedType.TypeName /// public UTF8String TypeName { get { return typeName; } set { typeName = value; } } /// protected UTF8String typeName; /// /// From column ExportedType.TypeNamespace /// public UTF8String TypeNamespace { get { return typeNamespace; } set { typeNamespace = value; } } /// protected UTF8String typeNamespace; /// /// From column ExportedType.Implementation /// public IImplementation Implementation { get { if (!implementation_isInitialized) InitializeImplementation(); return implementation; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif implementation = value; implementation_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected IImplementation implementation; /// protected bool implementation_isInitialized; void InitializeImplementation() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (implementation_isInitialized) return; implementation = GetImplementation_NoLock(); implementation_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual IImplementation GetImplementation_NoLock() { return null; } /// /// true if it's nested within another /// public bool IsNested { get { return DeclaringType != null; } } /// /// Gets the declaring type, if any /// public ExportedType DeclaringType { get { if (!implementation_isInitialized) InitializeImplementation(); return implementation as ExportedType; } } /// /// Modify property: = /// ( & ) | . /// /// Value to AND /// Value to OR void ModifyAttributes(TypeAttributes andMask, TypeAttributes 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 attributes = (attributes & (int)andMask) | (int)orMask; #endif } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyAttributes(bool set, TypeAttributes 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 visibility /// public TypeAttributes Visibility { get { return (TypeAttributes)attributes & TypeAttributes.VisibilityMask; } set { ModifyAttributes(~TypeAttributes.VisibilityMask, value & TypeAttributes.VisibilityMask); } } /// /// true if is set /// public bool IsNotPublic { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic; } } /// /// true if is set /// public bool IsPublic { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public; } } /// /// true if is set /// public bool IsNestedPublic { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic; } } /// /// true if is set /// public bool IsNestedPrivate { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate; } } /// /// true if is set /// public bool IsNestedFamily { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamily; } } /// /// true if is set /// public bool IsNestedAssembly { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedAssembly; } } /// /// true if is set /// public bool IsNestedFamilyAndAssembly { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamANDAssem; } } /// /// true if is set /// public bool IsNestedFamilyOrAssembly { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamORAssem; } } /// /// Gets/sets the layout /// public TypeAttributes Layout { get { return (TypeAttributes)attributes & TypeAttributes.LayoutMask; } set { ModifyAttributes(~TypeAttributes.LayoutMask, value & TypeAttributes.LayoutMask); } } /// /// true if is set /// public bool IsAutoLayout { get { return ((TypeAttributes)attributes & TypeAttributes.LayoutMask) == TypeAttributes.AutoLayout; } } /// /// true if is set /// public bool IsSequentialLayout { get { return ((TypeAttributes)attributes & TypeAttributes.LayoutMask) == TypeAttributes.SequentialLayout; } } /// /// true if is set /// public bool IsExplicitLayout { get { return ((TypeAttributes)attributes & TypeAttributes.LayoutMask) == TypeAttributes.ExplicitLayout; } } /// /// Gets/sets the bit /// public bool IsInterface { get { return ((TypeAttributes)attributes & TypeAttributes.Interface) != 0; } set { ModifyAttributes(value, TypeAttributes.Interface); } } /// /// Gets/sets the bit /// public bool IsClass { get { return ((TypeAttributes)attributes & TypeAttributes.Interface) == 0; } set { ModifyAttributes(!value, TypeAttributes.Interface); } } /// /// Gets/sets the bit /// public bool IsAbstract { get { return ((TypeAttributes)attributes & TypeAttributes.Abstract) != 0; } set { ModifyAttributes(value, TypeAttributes.Abstract); } } /// /// Gets/sets the bit /// public bool IsSealed { get { return ((TypeAttributes)attributes & TypeAttributes.Sealed) != 0; } set { ModifyAttributes(value, TypeAttributes.Sealed); } } /// /// Gets/sets the bit /// public bool IsSpecialName { get { return ((TypeAttributes)attributes & TypeAttributes.SpecialName) != 0; } set { ModifyAttributes(value, TypeAttributes.SpecialName); } } /// /// Gets/sets the bit /// public bool IsImport { get { return ((TypeAttributes)attributes & TypeAttributes.Import) != 0; } set { ModifyAttributes(value, TypeAttributes.Import); } } /// /// Gets/sets the bit /// public bool IsSerializable { get { return ((TypeAttributes)attributes & TypeAttributes.Serializable) != 0; } set { ModifyAttributes(value, TypeAttributes.Serializable); } } /// /// Gets/sets the bit /// public bool IsWindowsRuntime { get { return ((TypeAttributes)attributes & TypeAttributes.WindowsRuntime) != 0; } set { ModifyAttributes(value, TypeAttributes.WindowsRuntime); } } /// /// Gets/sets the string format /// public TypeAttributes StringFormat { get { return (TypeAttributes)attributes & TypeAttributes.StringFormatMask; } set { ModifyAttributes(~TypeAttributes.StringFormatMask, value & TypeAttributes.StringFormatMask); } } /// /// true if is set /// public bool IsAnsiClass { get { return ((TypeAttributes)attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AnsiClass; } } /// /// true if is set /// public bool IsUnicodeClass { get { return ((TypeAttributes)attributes & TypeAttributes.StringFormatMask) == TypeAttributes.UnicodeClass; } } /// /// true if is set /// public bool IsAutoClass { get { return ((TypeAttributes)attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AutoClass; } } /// /// true if is set /// public bool IsCustomFormatClass { get { return ((TypeAttributes)attributes & TypeAttributes.StringFormatMask) == TypeAttributes.CustomFormatClass; } } /// /// Gets/sets the bit /// public bool IsBeforeFieldInit { get { return ((TypeAttributes)attributes & TypeAttributes.BeforeFieldInit) != 0; } set { ModifyAttributes(value, TypeAttributes.BeforeFieldInit); } } /// /// Gets/sets the bit. See also /// public bool IsForwarder { get { return ((TypeAttributes)attributes & TypeAttributes.Forwarder) != 0; } set { ModifyAttributes(value, TypeAttributes.Forwarder); } } /// /// Gets/sets the bit /// public bool IsRuntimeSpecialName { get { return ((TypeAttributes)attributes & TypeAttributes.RTSpecialName) != 0; } set { ModifyAttributes(value, TypeAttributes.RTSpecialName); } } /// /// Gets/sets the bit /// public bool HasSecurity { get { return ((TypeAttributes)attributes & TypeAttributes.HasSecurity) != 0; } set { ModifyAttributes(value, TypeAttributes.HasSecurity); } } const int MAX_LOOP_ITERS = 50; /// /// true if this type has been moved to another assembly /// public bool MovedToAnotherAssembly { get { ExportedType et = this; for (int i = 0; i < MAX_LOOP_ITERS; i++) { var impl = et.Implementation; if (impl is AssemblyRef) return et.IsForwarder; et = impl as ExportedType; if (et == null) break; } return false; } } /// /// Resolves the type /// /// A instance or null if it couldn't be resolved public TypeDef Resolve() { return Resolve(null); } /// /// Resolves the type /// /// Source module or null /// A instance or null if it couldn't be resolved public TypeDef Resolve(ModuleDef sourceModule) { if (module == null) return null; return Resolve(sourceModule, this); } static TypeDef Resolve(ModuleDef sourceModule, ExportedType et) { for (int i = 0; i < MAX_LOOP_ITERS; i++) { if (et == null || et.module == null) break; var resolver = et.module.Context.AssemblyResolver; var etAsm = resolver.Resolve(et.DefinitionAssembly, sourceModule ?? et.module); if (etAsm == null) break; var td = etAsm.Find(et.FullName, false); if (td != null) return td; et = FindExportedType(etAsm, et); } return null; } static ExportedType FindExportedType(AssemblyDef asm, ExportedType et) { foreach (var mod in asm.Modules.GetSafeEnumerable()) { foreach (var et2 in mod.ExportedTypes.GetSafeEnumerable()) { if (new SigComparer(SigComparerOptions.DontCompareTypeScope).Equals(et, et2)) return et2; } } return null; } /// /// Resolves the type /// /// A instance /// If the type couldn't be resolved public TypeDef ResolveThrow() { var type = Resolve(); if (type != null) return type; throw new TypeResolveException(string.Format("Could not resolve type: {0} ({1})", this, DefinitionAssembly)); } /// /// Converts this instance to a /// /// A new instance public TypeRef ToTypeRef() { TypeRef result = null, prev = null; var mod = module; IImplementation impl = this; for (int i = 0; i < MAX_LOOP_ITERS && impl != null; i++) { var et = impl as ExportedType; if (et != null) { var newTr = mod.UpdateRowId(new TypeRefUser(mod, et.TypeNamespace, et.TypeName)); if (result == null) result = newTr; if (prev != null) prev.ResolutionScope = newTr; prev = newTr; impl = et.Implementation; continue; } var asmRef = impl as AssemblyRef; if (asmRef != null) { // prev is never null when we're here prev.ResolutionScope = asmRef; return result; } var file = impl as FileDef; if (file != null) { // prev is never null when we're here prev.ResolutionScope = FindModule(mod, file); return result; } break; } return result; } static ModuleDef FindModule(ModuleDef module, FileDef file) { if (module == null || file == null) return null; if (UTF8String.CaseInsensitiveEquals(module.Name, file.Name)) return module; var asm = module.Assembly; if (asm == null) return null; return asm.FindModule(file.Name); } /// public override string ToString() { return FullName; } } /// /// An ExportedType row created by the user and not present in the original .NET file /// public class ExportedTypeUser : ExportedType { /// /// Constructor /// /// Owner module public ExportedTypeUser(ModuleDef module) { this.module = module; } /// /// Constructor /// /// Owner module /// TypeDef ID /// Type name /// Type namespace /// Flags /// Implementation public ExportedTypeUser(ModuleDef module, uint typeDefId, UTF8String typeNamespace, UTF8String typeName, TypeAttributes flags, IImplementation implementation) { this.module = module; this.typeDefId = typeDefId; this.typeName = typeName; this.typeNamespace = typeNamespace; this.attributes = (int)flags; this.implementation = implementation; this.implementation_isInitialized = true; } } /// /// Created from a row in the ExportedType table /// sealed class ExportedTypeMD : ExportedType, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; readonly uint implementationRid; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.ExportedType, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// protected override IImplementation GetImplementation_NoLock() { return readerModule.ResolveImplementation(implementationRid); } /// /// Constructor /// /// The module which contains this ExportedType row /// Row ID /// If is null /// If is invalid public ExportedTypeMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.ExportedTypeTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("ExportedType rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; this.module = readerModule; uint name, @namespace; this.implementationRid = readerModule.TablesStream.ReadExportedTypeRow(origRid, out this.attributes, out this.typeDefId, out name, out @namespace); this.typeName = readerModule.StringsStream.ReadNoNull(name); this.typeNamespace = readerModule.StringsStream.ReadNoNull(@namespace); } } } dnlib-2.1_VS2010/src/DotNet/Extensions.cs000066400000000000000000000002521325033663500200360ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Extension methods /// public static partial class Extensions { } } dnlib-2.1_VS2010/src/DotNet/FieldAttributes.cs000066400000000000000000000036661325033663500210050ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// Field flags, see CorHdr.h/CorFieldAttr /// [Flags] public enum FieldAttributes : ushort { /// member access mask - Use this mask to retrieve accessibility information. FieldAccessMask = 0x0007, /// Member not referenceable. PrivateScope = 0x0000, /// Member not referenceable. CompilerControlled = PrivateScope, /// Accessible only by the parent type. Private = 0x0001, /// Accessible by sub-types only in this Assembly. FamANDAssem = 0x0002, /// Accessibly by anyone in the Assembly. Assembly = 0x0003, /// Accessible only by type and sub-types. Family = 0x0004, /// Accessibly by sub-types anywhere, plus anyone in assembly. FamORAssem = 0x0005, /// Accessibly by anyone who has visibility to this scope. Public = 0x0006, /// Defined on type, else per instance. Static = 0x0010, /// Field may only be initialized, not written to after init. InitOnly = 0x0020, /// Value is compile time constant. Literal = 0x0040, /// Field does not have to be serialized when type is remoted. NotSerialized = 0x0080, /// field is special. Name describes how. SpecialName = 0x0200, /// Implementation is forwarded through pinvoke. PinvokeImpl = 0x2000, /// Runtime(metadata internal APIs) should check name encoding. RTSpecialName = 0x0400, /// Field has marshalling information. HasFieldMarshal = 0x1000, /// Field has default. HasDefault = 0x8000, /// Field has RVA. HasFieldRVA = 0x0100, } } dnlib-2.1_VS2010/src/DotNet/FieldDef.cs000066400000000000000000000651441325033663500173540ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.PE; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the Field table /// public abstract class FieldDef : IHasConstant, IHasCustomAttribute, IHasFieldMarshal, IMemberForwarded, IHasCustomDebugInformation, IField, ITokenOperand, IMemberDef { /// /// The row id in its table /// protected uint rid; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// public MDToken MDToken { get { return new MDToken(Table.Field, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasConstantTag { get { return 0; } } /// public int HasCustomAttributeTag { get { return 1; } } /// public int HasFieldMarshalTag { get { return 0; } } /// public int MemberForwardedTag { get { return 0; } } /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public int HasCustomDebugInformationTag { get { return 1; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// /// From column Field.Flags /// public FieldAttributes Attributes { get { return (FieldAttributes)attributes; } set { attributes = (int)value; } } /// Attributes protected int attributes; /// /// From column Field.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// From column Field.Signature /// public CallingConventionSig Signature { get { return signature; } set { signature = value; } } /// protected CallingConventionSig signature; /// /// Gets/sets the field layout offset /// public uint? FieldOffset { get { if (!fieldOffset_isInitialized) InitializeFieldOffset(); return fieldOffset; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif fieldOffset = value; fieldOffset_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected uint? fieldOffset; /// protected bool fieldOffset_isInitialized; void InitializeFieldOffset() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (fieldOffset_isInitialized) return; fieldOffset = GetFieldOffset_NoLock(); fieldOffset_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual uint? GetFieldOffset_NoLock() { return null; } /// public MarshalType MarshalType { get { if (!marshalType_isInitialized) InitializeMarshalType(); return marshalType; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif marshalType = value; marshalType_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected MarshalType marshalType; /// protected bool marshalType_isInitialized; void InitializeMarshalType() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (marshalType_isInitialized) return; marshalType = GetMarshalType_NoLock(); marshalType_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual MarshalType GetMarshalType_NoLock() { return null; } /// Reset protected void ResetMarshalType() { marshalType_isInitialized = false; } /// /// Gets/sets the field RVA /// public RVA RVA { get { if (!rva_isInitialized) InitializeRVA(); return rva; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif rva = value; rva_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected RVA rva; /// protected bool rva_isInitialized; void InitializeRVA() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (rva_isInitialized) return; rva = GetRVA_NoLock(); rva_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual RVA GetRVA_NoLock() { return 0; } /// Reset protected void ResetRVA() { rva_isInitialized = false; } /// /// Gets/sets the initial value. Be sure to set to true if /// you write to this field. /// public byte[] InitialValue { get { if (!initialValue_isInitialized) InitializeInitialValue(); return initialValue; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif initialValue = value; initialValue_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected byte[] initialValue; /// protected bool initialValue_isInitialized; void InitializeInitialValue() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (initialValue_isInitialized) return; initialValue = GetInitialValue_NoLock(); initialValue_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual byte[] GetInitialValue_NoLock() { return null; } /// Reset protected void ResetInitialValue() { initialValue_isInitialized = false; } /// public ImplMap ImplMap { get { if (!implMap_isInitialized) InitializeImplMap(); return implMap; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif implMap = value; implMap_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected ImplMap implMap; /// protected bool implMap_isInitialized; void InitializeImplMap() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (implMap_isInitialized) return; implMap = GetImplMap_NoLock(); implMap_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual ImplMap GetImplMap_NoLock() { return null; } /// public Constant Constant { get { if (!constant_isInitialized) InitializeConstant(); return constant; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif constant = value; constant_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected Constant constant; /// protected bool constant_isInitialized; void InitializeConstant() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (constant_isInitialized) return; constant = GetConstant_NoLock(); constant_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual Constant GetConstant_NoLock() { return null; } /// Reset protected void ResetConstant() { constant_isInitialized = false; } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public bool HasImplMap { get { return ImplMap != null; } } /// /// Gets/sets the declaring type (owner type) /// public TypeDef DeclaringType { get { return declaringType2; } set { var currentDeclaringType = DeclaringType2; if (currentDeclaringType == value) return; if (currentDeclaringType != null) currentDeclaringType.Fields.Remove(this); // Will set DeclaringType2 = null if (value != null) value.Fields.Add(this); // Will set DeclaringType2 = value } } /// ITypeDefOrRef IMemberRef.DeclaringType { get { return declaringType2; } } /// /// Called by and should normally not be called by any user /// code. Use instead. Only call this if you must set the /// declaring type without inserting it in the declaring type's method list. /// public TypeDef DeclaringType2 { get { return declaringType2; } set { declaringType2 = value; } } /// protected TypeDef declaringType2; /// /// Gets/sets the /// public FieldSig FieldSig { get { return signature as FieldSig; } set { signature = value; } } /// public ModuleDef Module { get { var dt = declaringType2; return dt == null ? null : dt.Module; } } bool IIsTypeOrMethod.IsType { get { return false; } } bool IIsTypeOrMethod.IsMethod { get { return false; } } bool IMemberRef.IsField { get { return true; } } bool IMemberRef.IsTypeSpec { get { return false; } } bool IMemberRef.IsTypeRef { get { return false; } } bool IMemberRef.IsTypeDef { get { return false; } } bool IMemberRef.IsMethodSpec { get { return false; } } bool IMemberRef.IsMethodDef { get { return false; } } bool IMemberRef.IsMemberRef { get { return false; } } bool IMemberRef.IsFieldDef { get { return true; } } bool IMemberRef.IsPropertyDef { get { return false; } } bool IMemberRef.IsEventDef { get { return false; } } bool IMemberRef.IsGenericParam { get { return false; } } /// /// true if is not null /// public bool HasLayoutInfo { get { return FieldOffset != null; } } /// /// true if is not null /// public bool HasConstant { get { return Constant != null; } } /// /// Gets the constant element type or if there's no constant /// public ElementType ElementType { get { var c = Constant; return c == null ? ElementType.End : c.Type; } } /// /// true if is not null /// public bool HasMarshalType { get { return MarshalType != null; } } /// /// Gets/sets the field type /// public TypeSig FieldType { get { return FieldSig.GetFieldType(); } set { var sig = FieldSig; if (sig != null) sig.Type = value; } } /// /// Modify field: = /// ( & ) | . /// /// Value to AND /// Value to OR void ModifyAttributes(FieldAttributes andMask, FieldAttributes 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 attributes = (attributes & (int)andMask) | (int)orMask; #endif } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyAttributes(bool set, FieldAttributes 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 field access /// public FieldAttributes Access { get { return (FieldAttributes)attributes & FieldAttributes.FieldAccessMask; } set { ModifyAttributes(~FieldAttributes.FieldAccessMask, value & FieldAttributes.FieldAccessMask); } } /// /// true if is set /// public bool IsCompilerControlled { get { return IsPrivateScope; } } /// /// true if is set /// public bool IsPrivateScope { get { return ((FieldAttributes)attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.PrivateScope; } } /// /// true if is set /// public bool IsPrivate { get { return ((FieldAttributes)attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Private; } } /// /// true if is set /// public bool IsFamilyAndAssembly { get { return ((FieldAttributes)attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamANDAssem; } } /// /// true if is set /// public bool IsAssembly { get { return ((FieldAttributes)attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Assembly; } } /// /// true if is set /// public bool IsFamily { get { return ((FieldAttributes)attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Family; } } /// /// true if is set /// public bool IsFamilyOrAssembly { get { return ((FieldAttributes)attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamORAssem; } } /// /// true if is set /// public bool IsPublic { get { return ((FieldAttributes)attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public; } } /// /// Gets/sets the bit /// public bool IsStatic { get { return ((FieldAttributes)attributes & FieldAttributes.Static) != 0; } set { ModifyAttributes(value, FieldAttributes.Static); } } /// /// Gets/sets the bit /// public bool IsInitOnly { get { return ((FieldAttributes)attributes & FieldAttributes.InitOnly) != 0; } set { ModifyAttributes(value, FieldAttributes.InitOnly); } } /// /// Gets/sets the bit /// public bool IsLiteral { get { return ((FieldAttributes)attributes & FieldAttributes.Literal) != 0; } set { ModifyAttributes(value, FieldAttributes.Literal); } } /// /// Gets/sets the bit /// public bool IsNotSerialized { get { return ((FieldAttributes)attributes & FieldAttributes.NotSerialized) != 0; } set { ModifyAttributes(value, FieldAttributes.NotSerialized); } } /// /// Gets/sets the bit /// public bool IsSpecialName { get { return ((FieldAttributes)attributes & FieldAttributes.SpecialName) != 0; } set { ModifyAttributes(value, FieldAttributes.SpecialName); } } /// /// Gets/sets the bit /// public bool IsPinvokeImpl { get { return ((FieldAttributes)attributes & FieldAttributes.PinvokeImpl) != 0; } set { ModifyAttributes(value, FieldAttributes.PinvokeImpl); } } /// /// Gets/sets the bit /// public bool IsRuntimeSpecialName { get { return ((FieldAttributes)attributes & FieldAttributes.RTSpecialName) != 0; } set { ModifyAttributes(value, FieldAttributes.RTSpecialName); } } /// /// Gets/sets the bit /// public bool HasFieldMarshal { get { return ((FieldAttributes)attributes & FieldAttributes.HasFieldMarshal) != 0; } set { ModifyAttributes(value, FieldAttributes.HasFieldMarshal); } } /// /// Gets/sets the bit /// public bool HasDefault { get { return ((FieldAttributes)attributes & FieldAttributes.HasDefault) != 0; } set { ModifyAttributes(value, FieldAttributes.HasDefault); } } /// /// Gets/sets the bit /// public bool HasFieldRVA { get { return ((FieldAttributes)attributes & FieldAttributes.HasFieldRVA) != 0; } set { ModifyAttributes(value, FieldAttributes.HasFieldRVA); } } /// /// Returns the full name of this field /// public string FullName { get { var dt = declaringType2; return FullNameCreator.FieldFullName(dt == null ? null : dt.FullName, name, FieldSig, null, null); } } /// /// Gets the size of this field in bytes or 0 if unknown. /// public uint GetFieldSize() { uint size; if (!GetFieldSize(out size)) return 0; return size; } /// /// Gets the size of this field in bytes or 0 if unknown. /// /// Updated with size /// true if is valid, false otherwise public bool GetFieldSize(out uint size) { return GetFieldSize(declaringType2, FieldSig, out size); } /// /// Gets the size of this field in bytes or 0 if unknown. /// /// The declaring type of this /// The field signature of this /// Updated with size /// true if is valid, false otherwise protected bool GetFieldSize(TypeDef declaringType, FieldSig fieldSig, out uint size) { return GetFieldSize(declaringType, fieldSig, GetPointerSize(declaringType), out size); } /// /// Gets the size of this field in bytes or 0 if unknown. /// /// The declaring type of this /// The field signature of this /// Size of a pointer /// Updated with size /// true if is valid, false otherwise protected bool GetFieldSize(TypeDef declaringType, FieldSig fieldSig, int ptrSize, out uint size) { size = 0; if (fieldSig == null) return false; return GetClassSize(declaringType, fieldSig.Type, ptrSize, out size); } bool GetClassSize(TypeDef declaringType, TypeSig ts, int ptrSize, out uint size) { size = 0; ts = ts.RemovePinnedAndModifiers(); if (ts == null) return false; int size2 = ts.ElementType.GetPrimitiveSize(ptrSize); if (size2 >= 0) { size = (uint)size2; return true; } var tdrs = ts as TypeDefOrRefSig; if (tdrs == null) return false; var td = tdrs.TypeDef; if (td != null) return TypeDef.GetClassSize(td, out size); var tr = tdrs.TypeRef; if (tr != null) return TypeDef.GetClassSize(tr.Resolve(), out size); return false; } int GetPointerSize(TypeDef declaringType) { if (declaringType == null) return 4; var module = declaringType.Module; if (module == null) return 4; return module.GetPointerSize(); } /// public override string ToString() { return FullName; } } /// /// A Field row created by the user and not present in the original .NET file /// public class FieldDefUser : FieldDef { /// /// Default constructor /// public FieldDefUser() { } /// /// Constructor /// /// Name public FieldDefUser(UTF8String name) : this(name, null) { } /// /// Constructor /// /// Name /// Signature public FieldDefUser(UTF8String name, FieldSig signature) : this(name, signature, 0) { } /// /// Constructor /// /// Name /// Signature /// Flags public FieldDefUser(UTF8String name, FieldSig signature, FieldAttributes attributes) { this.name = name; this.signature = signature; this.attributes = (int)attributes; } } /// /// Created from a row in the Field table /// sealed class FieldDefMD : FieldDef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; readonly FieldAttributes origAttributes; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.Field, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(declaringType2), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// protected override uint? GetFieldOffset_NoLock() { return readerModule.TablesStream.ReadFieldLayoutRow2(readerModule.MetaData.GetFieldLayoutRid(origRid)); } /// protected override MarshalType GetMarshalType_NoLock() { return readerModule.ReadMarshalType(Table.Field, origRid, new GenericParamContext(declaringType2)); } /// protected override RVA GetRVA_NoLock() { RVA rva2; GetFieldRVA_NoLock(out rva2); return rva2; } /// protected override byte[] GetInitialValue_NoLock() { RVA rva2; if (!GetFieldRVA_NoLock(out rva2)) return null; return ReadInitialValue_NoLock(rva2); } /// protected override ImplMap GetImplMap_NoLock() { return readerModule.ResolveImplMap(readerModule.MetaData.GetImplMapRid(Table.Field, origRid)); } /// protected override Constant GetConstant_NoLock() { return readerModule.ResolveConstant(readerModule.MetaData.GetConstantRid(Table.Field, origRid)); } /// /// Constructor /// /// The module which contains this Field row /// Row ID /// If is null /// If is invalid public FieldDefMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.FieldTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("Field rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; uint name; uint signature = readerModule.TablesStream.ReadFieldRow(origRid, out this.attributes, out name); this.name = readerModule.StringsStream.ReadNoNull(name); this.origAttributes = (FieldAttributes)attributes; this.declaringType2 = readerModule.GetOwnerType(this); this.signature = readerModule.ReadSignature(signature, new GenericParamContext(declaringType2)); } internal FieldDefMD InitializeAll() { MemberMDInitializer.Initialize(CustomAttributes); MemberMDInitializer.Initialize(Attributes); MemberMDInitializer.Initialize(Name); MemberMDInitializer.Initialize(Signature); MemberMDInitializer.Initialize(FieldOffset); MemberMDInitializer.Initialize(MarshalType); MemberMDInitializer.Initialize(RVA); MemberMDInitializer.Initialize(InitialValue); MemberMDInitializer.Initialize(ImplMap); MemberMDInitializer.Initialize(Constant); MemberMDInitializer.Initialize(DeclaringType); return this; } bool GetFieldRVA_NoLock(out RVA rva) { if ((origAttributes & FieldAttributes.HasFieldRVA) == 0) { rva = 0; return false; } return readerModule.TablesStream.ReadFieldRVARow(readerModule.MetaData.GetFieldRVARid(origRid), out rva); } byte[] ReadInitialValue_NoLock(RVA rva) { uint size; if (!GetFieldSize(declaringType2, signature as FieldSig, out size)) return null; if (size >= int.MaxValue) return null; return readerModule.ReadDataAt(rva, (int)size); } } } dnlib-2.1_VS2010/src/DotNet/FileAttributes.cs000066400000000000000000000006351325033663500206320ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// File row flags. See CorHdr.h/CorFileFlags /// [Flags] public enum FileAttributes : uint { /// This is not a resource file ContainsMetaData = 0x0000, /// This is a resource file or other non-metadata-containing file ContainsNoMetaData = 0x0001, } } dnlib-2.1_VS2010/src/DotNet/FileDef.cs000066400000000000000000000157241325033663500172070ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the File table /// public abstract class FileDef : IHasCustomAttribute, IImplementation, IHasCustomDebugInformation, IManagedEntryPoint { /// /// The row id in its table /// protected uint rid; /// public MDToken MDToken { get { return new MDToken(Table.File, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 16; } } /// public int ImplementationTag { get { return 0; } } /// /// From column File.Flags /// public FileAttributes Flags { get { return (FileAttributes)attributes; } set { attributes = (int)value; } } /// Attributes protected int attributes; /// /// From column File.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// From column File.HashValue /// public byte[] HashValue { get { return hashValue; } set { hashValue = value; } } /// protected byte[] hashValue; /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 16; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyAttributes(bool set, FileAttributes 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 ContainsMetaData { get { return ((FileAttributes)attributes & FileAttributes.ContainsNoMetaData) == 0; } set { ModifyAttributes(!value, FileAttributes.ContainsNoMetaData); } } /// /// Gets/sets the bit /// public bool ContainsNoMetaData { get { return ((FileAttributes)attributes & FileAttributes.ContainsNoMetaData) != 0; } set { ModifyAttributes(value, FileAttributes.ContainsNoMetaData); } } /// public string FullName { get { return UTF8String.ToSystemStringOrEmpty(name); } } /// public override string ToString() { return FullName; } } /// /// A File row created by the user and not present in the original .NET file /// public class FileDefUser : FileDef { /// /// Default constructor /// public FileDefUser() { } /// /// Constructor /// /// Name of file /// Flags /// File hash public FileDefUser(UTF8String name, FileAttributes flags, byte[] hashValue) { this.name = name; this.attributes = (int)flags; this.hashValue = hashValue; } } /// /// Created from a row in the File table /// sealed class FileDefMD : FileDef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.File, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this File row /// Row ID /// If is null /// If is invalid public FileDefMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.FileTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("File rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; uint name; uint hashValue = readerModule.TablesStream.ReadFileRow(origRid, out this.attributes, out name); this.name = readerModule.StringsStream.ReadNoNull(name); this.hashValue = readerModule.BlobStream.Read(hashValue); } } } dnlib-2.1_VS2010/src/DotNet/FrameworkRedirect.cs000066400000000000000000000666121325033663500213320ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; namespace dnlib.DotNet { /// /// Redirects .NET framework assembly references from older to newer versions /// public static class FrameworkRedirect { static readonly Dictionary frmRedir2; static readonly Dictionary frmRedir4; struct FrameworkRedirectInfo { public readonly PublicKeyToken publicKeyToken; public readonly Version redirectVersion; public FrameworkRedirectInfo(string publicKeyToken, string redirectVersion) { this.publicKeyToken = new PublicKeyToken(publicKeyToken); this.redirectVersion = new Version(redirectVersion); } } static FrameworkRedirect() { frmRedir2 = new Dictionary(StringComparer.OrdinalIgnoreCase); frmRedir4 = new Dictionary(StringComparer.OrdinalIgnoreCase); InitFrameworkRedirectV2(); InitFrameworkRedirectV4(); } static void InitFrameworkRedirectV2() { frmRedir2["Accessibility"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["cscompmgd"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["CustomMarshalers"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["IEExecRemote"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["IEHost"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["IIEHost"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["ISymWrapper"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["Microsoft.JScript"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.VisualBasic"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.VisualBasic.Compatibility"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.VisualBasic.Compatibility.Data"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.VisualBasic.Vsa"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.VisualC"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.Vsa"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft.Vsa.Vb.CodeDOMProcessor"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["Microsoft_VsaVb"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0"); frmRedir2["mscorcfg"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["mscorlib"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Configuration"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Configuration.Install"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Data"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Data.OracleClient"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Data.SqlXml"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Deployment"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Design"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.DirectoryServices"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.DirectoryServices.Protocols"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Drawing"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Drawing.Design"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.EnterpriseServices"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Management"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Messaging"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Runtime.Remoting"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Runtime.Serialization.Formatters.Soap"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Security"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.ServiceProcess"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Transactions"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Web"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Web.Mobile"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Web.RegularExpressions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Web.Services"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["System.Windows.Forms"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["System.Xml"] = new FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0"); frmRedir2["vjscor"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["VJSharpCodeProvider"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjsJBC"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjslib"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjslibcw"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["Vjssupuilib"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjsvwaux"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjswfc"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["VJSWfcBrowserStubLib"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjswfccw"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir2["vjswfchtml"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); } static void InitFrameworkRedirectV4() { frmRedir4["Accessibility"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["CustomMarshalers"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["ISymWrapper"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.JScript"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0"); frmRedir4["Microsoft.VisualBasic"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0"); frmRedir4["Microsoft.VisualBasic.Compatibility"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0"); frmRedir4["Microsoft.VisualBasic.Compatibility.Data"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0"); frmRedir4["Microsoft.VisualC"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0"); frmRedir4["mscorlib"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Configuration"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Configuration.Install"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Data"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.OracleClient"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.SqlXml"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Deployment"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Design"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.DirectoryServices"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.DirectoryServices.Protocols"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Drawing"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Drawing.Design"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.EnterpriseServices"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Management"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Messaging"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Remoting"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Runtime.Serialization.Formatters.Soap"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Security"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceProcess"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Transactions"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Web"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Web.Mobile"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Web.RegularExpressions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Web.Services"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Windows.Forms"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Xml"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["AspNetMMCExt"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["sysglobl"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.Build.Engine"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.Build.Framework"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["PresentationCFFRasterizer"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationCore"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework.Aero"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework.Classic"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework.Luna"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework.Royale"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationUI"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["ReachFramework"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Printing"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Speech"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["UIAutomationClient"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["UIAutomationClientsideProviders"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["UIAutomationProvider"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["UIAutomationTypes"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["WindowsBase"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["WindowsFormsIntegration"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["SMDiagnostics"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.IdentityModel"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.IdentityModel.Selectors"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.IO.Log"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Serialization"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.ServiceModel"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.ServiceModel.Install"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.ServiceModel.WasHosting"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Workflow.Activities"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Workflow.ComponentModel"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Workflow.Runtime"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["Microsoft.Transactions.Bridge"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.Transactions.Bridge.Dtc"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.AddIn"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.AddIn.Contract"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ComponentModel.Composition"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Core"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.DataSetExtensions"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.Linq"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Xml.Linq"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.DirectoryServices.AccountManagement"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Management.Instrumentation"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Net"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceModel.Web"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.Extensions"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.Extensions.Design"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Windows.Presentation"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.WorkflowServices"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ComponentModel.DataAnnotations"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Data.Entity"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.Entity.Design"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.Services"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.Services.Client"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Data.Services.Design"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Web.Abstractions"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.DynamicData"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.DynamicData.Design"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.Entity"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Web.Entity.Design"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Web.Routing"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["Microsoft.Build"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.CSharp"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Dynamic"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Numerics"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Xaml"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["Microsoft.Workflow.Compiler"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["Microsoft.Activities.Build"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["Microsoft.Build.Conversion.v4.0"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.Build.Tasks.v4.0"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.Build.Utilities.v4.0"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["Microsoft.Internal.Tasks.Dataflow"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["Microsoft.VisualBasic.Activities.Compiler"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0"); frmRedir4["Microsoft.VisualC.STLCLR"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0"); frmRedir4["Microsoft.Windows.ApplicationServer.Applications"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationBuildTasks"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework.Aero2"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework.AeroLite"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["PresentationFramework-SystemCore"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["PresentationFramework-SystemData"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["PresentationFramework-SystemDrawing"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["PresentationFramework-SystemXml"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["PresentationFramework-SystemXmlLinq"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Activities"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Activities.Core.Presentation"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Activities.DurableInstancing"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Activities.Presentation"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ComponentModel.Composition.Registration"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Device"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.IdentityModel.Services"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.IO.Compression"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.IO.Compression.FileSystem"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Net.Http"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Net.Http.WebRequest"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection.Context"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Runtime.Caching"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.DurableInstancing"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Runtime.WindowsRuntime"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Runtime.WindowsRuntime.UI.Xaml"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.ServiceModel.Activation"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ServiceModel.Activities"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ServiceModel.Channels"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ServiceModel.Discovery"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ServiceModel.Internals"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ServiceModel.Routing"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.ServiceModel.ServiceMoniker40"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Web.ApplicationServices"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.DataVisualization"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Web.DataVisualization.Design"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Windows.Controls.Ribbon"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Windows.Forms.DataVisualization"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Windows.Forms.DataVisualization.Design"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Windows.Input.Manipulations"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); frmRedir4["System.Xaml.Hosting"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["XamlBuildTask"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["XsdBuildTask"] = new FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0"); frmRedir4["System.Collections"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Collections.Concurrent"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ComponentModel"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ComponentModel.Annotations"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ComponentModel.EventBasedAsync"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Diagnostics.Contracts"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Diagnostics.Debug"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Diagnostics.Tools"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Diagnostics.Tracing"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Dynamic.Runtime"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Globalization"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.IO"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Linq"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Linq.Expressions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Linq.Parallel"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Linq.Queryable"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Net.NetworkInformation"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Net.Primitives"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Net.Requests"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ObjectModel"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection.Emit"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection.Emit.ILGeneration"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection.Emit.Lightweight"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection.Extensions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Reflection.Primitives"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Resources.ResourceManager"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Extensions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.InteropServices"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.InteropServices.WindowsRuntime"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Numerics"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Serialization.Json"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Serialization.Primitives"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Runtime.Serialization.Xml"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Security.Principal"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceModel.Duplex"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceModel.Http"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceModel.NetTcp"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceModel.Primitives"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.ServiceModel.Security"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Text.Encoding"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Text.Encoding.Extensions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Text.RegularExpressions"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Threading"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Threading.Timer"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Threading.Tasks"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Threading.Tasks.Parallel"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Xml.ReaderWriter"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Xml.XDocument"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Xml.XmlSerializer"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Net.Http.Rtc"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Windows"] = new FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0"); frmRedir4["System.Xml.Serialization"] = new FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0"); } /// /// Redirects a .NET framework assembly from an older version to the correct version /// loaded at runtime. /// /// Current assembly reference that might get updated /// Module using the assembly reference public static void ApplyFrameworkRedirect(ref IAssembly assembly, ModuleDef sourceModule) { if (sourceModule == null) return; if (!Utils.LocaleEquals(assembly.Culture, "")) return; if (!sourceModule.IsClr20 && !sourceModule.IsClr40) return; FrameworkRedirectInfo redirect; if (!(sourceModule.IsClr20 ? frmRedir2 : frmRedir4).TryGetValue(assembly.Name, out redirect)) return; if (PublicKeyBase.TokenCompareTo(assembly.PublicKeyOrToken, redirect.publicKeyToken) != 0) return; if (Utils.CompareTo(assembly.Version, redirect.redirectVersion) == 0) return; assembly = new AssemblyNameInfo(assembly); assembly.Version = redirect.redirectVersion; } } } dnlib-2.1_VS2010/src/DotNet/FullNameCreator.cs000066400000000000000000002257251325033663500207400ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Text; using dnlib.Threading; namespace dnlib.DotNet { /// /// Helps create a name /// public interface IFullNameCreatorHelper { /// /// Checks whether the assembly name should be included when printing /// the full type name. The assembly name isn't required in custom attributes /// when the type already exists in the same module as the CA, or if the type /// exists in mscorlib. /// /// The type (TypeDef, TypeRef or ExportedType) /// or null /// true if the assembly name must be included, false otherwise bool MustUseAssemblyName(IType type); } /// /// Creates type names, method names, etc. /// public struct FullNameCreator { const string RECURSION_ERROR_RESULT_STRING = "<<>>"; const string NULLVALUE = "<<>>"; readonly StringBuilder sb; readonly bool isReflection; readonly IFullNameCreatorHelper helper; GenericArguments genericArguments; RecursionCounter recursionCounter; /// /// Checks whether the assembly name should be included when printing the full name. /// See for more info. /// /// Owner module /// The type (TypeDef, TypeRef or ExportedType) /// or null /// true if the assembly name must be included, false otherwise public static bool MustUseAssemblyName(ModuleDef module, IType type) { var td = type as TypeDef; if (td != null) return td.Module != module; var tr = type as TypeRef; if (tr == null) return true; if (tr.ResolutionScope == AssemblyRef.CurrentAssembly) return false; if (!tr.DefinitionAssembly.IsCorLib()) return true; // If it's present in this module, but it's a corlib type, then we will need the // assembly name. return module.Find(tr) != null; } /// /// Returns the full name of a /// /// The TypeRef /// Set if output should be compatible with reflection /// Helps print the name /// String builder to use or null /// The full name public static string FullName(IType type, bool isReflection, IFullNameCreatorHelper helper, StringBuilder sb) { return FullNameSB(type, isReflection, helper, sb).ToString(); } /// /// Returns the full name of a /// /// The TypeRef /// Set if output should be compatible with reflection /// Helps print the name /// String builder to use or null /// The full name public static StringBuilder FullNameSB(IType type, bool isReflection, IFullNameCreatorHelper helper, StringBuilder sb) { var td = type as TypeDef; if (td != null) return FullNameSB(td, isReflection, helper, sb); var tr = type as TypeRef; if (tr != null) return FullNameSB(tr, isReflection, helper, sb); var ts = type as TypeSpec; if (ts != null) return FullNameSB(ts, isReflection, helper, sb); var sig = type as TypeSig; if (sig != null) return FullNameSB(sig, isReflection, helper, null, null, sb); var et = type as ExportedType; if (et != null) return FullNameSB(et, isReflection, helper, sb); return sb ?? new StringBuilder(); } /// /// Returns the name of a /// /// The TypeRef /// Set if output should be compatible with reflection /// String builder to use or null /// The full name public static string Name(IType type, bool isReflection, StringBuilder sb) { return NameSB(type, isReflection, sb).ToString(); } /// /// Returns the name of a /// /// The TypeRef /// Set if output should be compatible with reflection /// String builder to use or null /// The full name public static StringBuilder NameSB(IType type, bool isReflection, StringBuilder sb) { var td = type as TypeDef; if (td != null) return NameSB(td, isReflection, sb); var tr = type as TypeRef; if (tr != null) return NameSB(tr, isReflection, sb); var ts = type as TypeSpec; if (ts != null) return NameSB(ts, isReflection, sb); var sig = type as TypeSig; if (sig != null) return NameSB(sig, false, sb); var et = type as ExportedType; if (et != null) return NameSB(et, isReflection, sb); return sb ?? new StringBuilder(); } /// /// Returns the namespace of a /// /// The TypeRef /// Set if output should be compatible with reflection /// String builder to use or null /// The full name public static string Namespace(IType type, bool isReflection, StringBuilder sb) { return NamespaceSB(type, isReflection, sb).ToString(); } /// /// Returns the namespace of a /// /// The TypeRef /// Set if output should be compatible with reflection /// String builder to use or null /// The full name public static StringBuilder NamespaceSB(IType type, bool isReflection, StringBuilder sb) { var td = type as TypeDef; if (td != null) return NamespaceSB(td, isReflection, sb); var tr = type as TypeRef; if (tr != null) return NamespaceSB(tr, isReflection, sb); var ts = type as TypeSpec; if (ts != null) return NamespaceSB(ts, isReflection, sb); var sig = type as TypeSig; if (sig != null) return NamespaceSB(sig, false, sb); var et = type as ExportedType; if (et != null) return NamespaceSB(et, isReflection, sb); return sb ?? new StringBuilder(); } /// /// Returns the assembly qualified full name of a /// /// The IType /// Helps print the name /// String builder to use or null /// The assembly qualified full name public static string AssemblyQualifiedName(IType type, IFullNameCreatorHelper helper = null, StringBuilder sb = null) { return AssemblyQualifiedNameSB(type, helper, sb).ToString(); } /// /// Returns the assembly qualified full name of a /// /// The IType /// Helps print the name /// String builder to use or null /// The assembly qualified full name public static StringBuilder AssemblyQualifiedNameSB(IType type, IFullNameCreatorHelper helper, StringBuilder sb) { var td = type as TypeDef; if (td != null) return AssemblyQualifiedNameSB(td, helper, sb); var tr = type as TypeRef; if (tr != null) return AssemblyQualifiedNameSB(tr, helper, sb); var ts = type as TypeSpec; if (ts != null) return AssemblyQualifiedNameSB(ts, helper, sb); var sig = type as TypeSig; if (sig != null) return AssemblyQualifiedNameSB(sig, helper, sb); var et = type as ExportedType; if (et != null) return AssemblyQualifiedNameSB(et, helper, sb); return sb ?? new StringBuilder(); } /// /// Returns the full name of a property /// /// Declaring type full name or null if none /// Name of property /// Property signature /// Type generic arguments or null if none /// String builder to use or null /// Property full name public static string PropertyFullName(string declaringType, UTF8String name, CallingConventionSig propertySig, IList typeGenArgs = null, StringBuilder sb = null) { return PropertyFullNameSB(declaringType, name, propertySig, typeGenArgs, sb).ToString(); } /// /// Returns the full name of a property /// /// Declaring type full name or null if none /// Name of property /// Property signature /// Type generic arguments or null if none /// String builder to use or null /// Property full name public static StringBuilder PropertyFullNameSB(string declaringType, UTF8String name, CallingConventionSig propertySig, IList typeGenArgs, StringBuilder sb) { var fnc = new FullNameCreator(false, null, sb); if (typeGenArgs != null) { fnc.genericArguments = new GenericArguments(); fnc.genericArguments.PushTypeArgs(typeGenArgs); } fnc.CreatePropertyFullName(declaringType, name, propertySig); return fnc.sb ?? new StringBuilder(); } /// /// Returns the full name of a property /// /// Declaring type full name or null if none /// Name of property /// Event type /// Type generic arguments or null if none /// String builder to use or null /// Property full name public static string EventFullName(string declaringType, UTF8String name, ITypeDefOrRef typeDefOrRef, IList typeGenArgs = null, StringBuilder sb = null) { return EventFullNameSB(declaringType, name, typeDefOrRef, typeGenArgs, sb).ToString(); } /// /// Returns the full name of a property /// /// Declaring type full name or null if none /// Name of property /// Event type /// Type generic arguments or null if none /// String builder to use or null /// Property full name public static StringBuilder EventFullNameSB(string declaringType, UTF8String name, ITypeDefOrRef typeDefOrRef, IList typeGenArgs, StringBuilder sb) { var fnc = new FullNameCreator(false, null, sb); if (typeGenArgs != null) { fnc.genericArguments = new GenericArguments(); fnc.genericArguments.PushTypeArgs(typeGenArgs); } fnc.CreateEventFullName(declaringType, name, typeDefOrRef); return fnc.sb ?? new StringBuilder(); } /// /// Returns the full name of a field /// /// Declaring type full name or null if none /// Name of field /// Field signature /// Type generic arguments or null if none /// String builder to use or null /// Field full name public static string FieldFullName(string declaringType, string name, FieldSig fieldSig, IList typeGenArgs = null, StringBuilder sb = null) { return FieldFullNameSB(declaringType, name, fieldSig, typeGenArgs, sb).ToString(); } /// /// Returns the full name of a field /// /// Declaring type full name or null if none /// Name of field /// Field signature /// Type generic arguments or null if none /// String builder to use or null /// Field full name public static StringBuilder FieldFullNameSB(string declaringType, string name, FieldSig fieldSig, IList typeGenArgs, StringBuilder sb) { var fnc = new FullNameCreator(false, null, sb); if (typeGenArgs != null) { fnc.genericArguments = new GenericArguments(); fnc.genericArguments.PushTypeArgs(typeGenArgs); } fnc.CreateFieldFullName(declaringType, name, fieldSig); return fnc.sb ?? new StringBuilder(); } /// /// Returns the full name of a method /// /// Declaring type full name or null if none /// Name of method or null if none /// Method signature /// Type generic arguments or null if none /// Method generic arguments or null if none /// Generic parameter owner method or null /// String builder to use or null /// Method full name public static string MethodFullName(string declaringType, string name, MethodSig methodSig, IList typeGenArgs = null, IList methodGenArgs = null, MethodDef gppMethod = null, StringBuilder sb = null) { return MethodFullNameSB(declaringType, name, methodSig, typeGenArgs, methodGenArgs, gppMethod, sb).ToString(); } /// /// Returns the full name of a method /// /// Declaring type full name or null if none /// Name of method or null if none /// Method signature /// Type generic arguments or null if none /// Method generic arguments or null if none /// Generic parameter owner method or null /// String builder to use or null /// Method full name public static StringBuilder MethodFullNameSB(string declaringType, string name, MethodSig methodSig, IList typeGenArgs, IList methodGenArgs, MethodDef gppMethod, StringBuilder sb) { var fnc = new FullNameCreator(false, null, sb); if (typeGenArgs != null || methodGenArgs != null) fnc.genericArguments = new GenericArguments(); if (typeGenArgs != null) fnc.genericArguments.PushTypeArgs(typeGenArgs); if (methodGenArgs != null) fnc.genericArguments.PushMethodArgs(methodGenArgs); fnc.CreateMethodFullName(declaringType, name, methodSig, gppMethod); return fnc.sb ?? new StringBuilder(); } /// /// Returns the full name of a property sig /// /// Property sig /// String builder to use or null /// Property sig full name public static string MethodBaseSigFullName(MethodBaseSig sig, StringBuilder sb = null) { return MethodBaseSigFullNameSB(sig, sb).ToString(); } /// /// Returns the full name of a property sig /// /// Property sig /// String builder to use or null /// Property sig full name public static StringBuilder MethodBaseSigFullNameSB(MethodBaseSig sig, StringBuilder sb) { var fnc = new FullNameCreator(false, null, sb); fnc.CreateMethodFullName(null, null, sig, null); return fnc.sb ?? new StringBuilder(); } /// /// Returns the full name of a sig /// /// Declaring type or null /// Name or null /// Method sig /// Owner method or null /// String builder to use or null /// Sig full name public static string MethodBaseSigFullName(string declType, string name, MethodBaseSig sig, MethodDef gppMethod, StringBuilder sb = null) { return MethodBaseSigFullNameSB(declType, name, sig, gppMethod, sb).ToString(); } /// /// Returns the full name of a sig /// /// Declaring type or null /// Name or null /// Method sig /// Owner method or null /// String builder to use or null /// Sig full name public static StringBuilder MethodBaseSigFullNameSB(string declType, string name, MethodBaseSig sig, MethodDef gppMethod, StringBuilder sb) { var fnc = new FullNameCreator(false, null, sb); fnc.CreateMethodFullName(declType, name, sig, gppMethod); return fnc.sb ?? new StringBuilder(); } /// /// Returns the namespace of a /// /// The TypeRef /// Set if output should be compatible with reflection /// String builder to use or null /// The namespace public static string Namespace(TypeRef typeRef, bool isReflection, StringBuilder sb = null) { return NamespaceSB(typeRef, isReflection, sb).ToString(); } /// /// Returns the namespace of a /// /// The TypeRef /// Set if output should be compatible with reflection /// String builder to use or null /// The namespace public static StringBuilder NamespaceSB(TypeRef typeRef, bool isReflection, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, null, sb); fnc.CreateNamespace(typeRef); return fnc.sb ?? new StringBuilder(); } /// /// Returns the name of a /// /// The TypeRef /// Set if output should be compatible with reflection /// String builder to use or null /// The name public static string Name(TypeRef typeRef, bool isReflection, StringBuilder sb = null) { return NameSB(typeRef, isReflection, sb).ToString(); } /// /// Returns the name of a /// /// The TypeRef /// Set if output should be compatible with reflection /// String builder to use or null /// The name public static StringBuilder NameSB(TypeRef typeRef, bool isReflection, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, null, sb); fnc.CreateName(typeRef); return fnc.sb ?? new StringBuilder(); } /// /// Returns the full name of a /// /// The TypeRef /// Set if output should be compatible with reflection /// Helps print the name /// String builder to use or null /// The full name public static string FullName(TypeRef typeRef, bool isReflection, IFullNameCreatorHelper helper = null, StringBuilder sb = null) { return FullNameSB(typeRef, isReflection, helper, sb).ToString(); } /// /// Returns the full name of a /// /// The TypeRef /// Set if output should be compatible with reflection /// Helps print the name /// String builder to use or null /// The full name public static StringBuilder FullNameSB(TypeRef typeRef, bool isReflection, IFullNameCreatorHelper helper, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, helper, sb); fnc.CreateFullName(typeRef); return fnc.sb ?? new StringBuilder(); } /// /// Returns the assembly qualified full name of a /// /// The TypeRef /// Helps print the name /// String builder to use or null /// The assembly qualified full name public static string AssemblyQualifiedName(TypeRef typeRef, IFullNameCreatorHelper helper = null, StringBuilder sb = null) { return AssemblyQualifiedNameSB(typeRef, helper, sb).ToString(); } /// /// Returns the assembly qualified full name of a /// /// The TypeRef /// Helps print the name /// String builder to use or null /// The assembly qualified full name public static StringBuilder AssemblyQualifiedNameSB(TypeRef typeRef, IFullNameCreatorHelper helper, StringBuilder sb) { var fnc = new FullNameCreator(true, helper, sb); fnc.CreateAssemblyQualifiedName(typeRef); return fnc.sb ?? new StringBuilder(); } /// /// Returns the assembly where this type is defined /// /// The TypeRef /// A or null if none found public static IAssembly DefinitionAssembly(TypeRef typeRef) { return new FullNameCreator().GetDefinitionAssembly(typeRef); } /// /// Gets the scope /// /// The TypeRef /// The or null if none found public static IScope Scope(TypeRef typeRef) { return new FullNameCreator().GetScope(typeRef); } /// /// Returns the owner module. The type was created from metadata in this module. /// /// The TypeRef /// A or null if none found public static ModuleDef OwnerModule(TypeRef typeRef) { return new FullNameCreator().GetOwnerModule(typeRef); } /// /// Returns the namespace of a /// /// The TypeDef /// Set if output should be compatible with reflection /// String builder to use or null /// The namespace public static string Namespace(TypeDef typeDef, bool isReflection, StringBuilder sb = null) { return NamespaceSB(typeDef, isReflection, sb).ToString(); } /// /// Returns the namespace of a /// /// The TypeDef /// Set if output should be compatible with reflection /// String builder to use or null /// The namespace public static StringBuilder NamespaceSB(TypeDef typeDef, bool isReflection, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, null, sb); fnc.CreateNamespace(typeDef); return fnc.sb ?? new StringBuilder(); } /// /// Returns the name of a /// /// The TypeDef /// Set if output should be compatible with reflection /// String builder to use or null /// The name public static string Name(TypeDef typeDef, bool isReflection, StringBuilder sb = null) { return NameSB(typeDef, isReflection, sb).ToString(); } /// /// Returns the name of a /// /// The TypeDef /// Set if output should be compatible with reflection /// String builder to use or null /// The name public static StringBuilder NameSB(TypeDef typeDef, bool isReflection, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, null, sb); fnc.CreateName(typeDef); return fnc.sb ?? new StringBuilder(); } /// /// Returns the full name of a /// /// The TypeDef /// Set if output should be compatible with reflection /// Helps print the name /// String builder to use or null /// The full name public static string FullName(TypeDef typeDef, bool isReflection, IFullNameCreatorHelper helper = null, StringBuilder sb = null) { return FullNameSB(typeDef, isReflection, helper, sb).ToString(); } /// /// Returns the full name of a /// /// The TypeDef /// Set if output should be compatible with reflection /// Helps print the name /// String builder to use or null /// The full name public static StringBuilder FullNameSB(TypeDef typeDef, bool isReflection, IFullNameCreatorHelper helper, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, helper, sb); fnc.CreateFullName(typeDef); return fnc.sb ?? new StringBuilder(); } /// /// Returns the assembly qualified full name of a /// /// The TypeDef /// Helps print the name /// String builder to use or null /// The assembly qualified full name public static string AssemblyQualifiedName(TypeDef typeDef, IFullNameCreatorHelper helper = null, StringBuilder sb = null) { return AssemblyQualifiedNameSB(typeDef, helper, sb).ToString(); } /// /// Returns the assembly qualified full name of a /// /// The TypeDef /// Helps print the name /// String builder to use or null /// The assembly qualified full name public static StringBuilder AssemblyQualifiedNameSB(TypeDef typeDef, IFullNameCreatorHelper helper, StringBuilder sb) { var fnc = new FullNameCreator(true, helper, sb); fnc.CreateAssemblyQualifiedName(typeDef); return fnc.sb ?? new StringBuilder(); } /// /// Returns the assembly where this type is defined /// /// The TypeDef /// A or null if none found public static IAssembly DefinitionAssembly(TypeDef typeDef) { return new FullNameCreator().GetDefinitionAssembly(typeDef); } /// /// Returns the owner module. The type was created from metadata in this module. /// /// The TypeDef /// A or null if none found public static ModuleDef OwnerModule(TypeDef typeDef) { return new FullNameCreator().GetOwnerModule(typeDef); } /// /// Returns the namespace of a /// /// The TypeSpec /// Set if output should be compatible with reflection /// String builder to use or null /// The namespace public static string Namespace(TypeSpec typeSpec, bool isReflection, StringBuilder sb = null) { return NamespaceSB(typeSpec, isReflection, sb).ToString(); } /// /// Returns the namespace of a /// /// The TypeSpec /// Set if output should be compatible with reflection /// String builder to use or null /// The namespace public static StringBuilder NamespaceSB(TypeSpec typeSpec, bool isReflection, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, null, sb); fnc.CreateNamespace(typeSpec); return fnc.sb ?? new StringBuilder(); } /// /// Returns the name of a /// /// The TypeSpec /// Set if output should be compatible with reflection /// String builder to use or null /// The name public static string Name(TypeSpec typeSpec, bool isReflection, StringBuilder sb = null) { return NameSB(typeSpec, isReflection, sb).ToString(); } /// /// Returns the name of a /// /// The TypeSpec /// Set if output should be compatible with reflection /// String builder to use or null /// The name public static StringBuilder NameSB(TypeSpec typeSpec, bool isReflection, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, null, sb); fnc.CreateName(typeSpec); return fnc.sb ?? new StringBuilder(); } /// /// Returns the full name of a /// /// The TypeSpec /// Set if output should be compatible with reflection /// Helps print the name /// String builder to use or null /// The full name public static string FullName(TypeSpec typeSpec, bool isReflection, IFullNameCreatorHelper helper = null, StringBuilder sb = null) { return FullNameSB(typeSpec, isReflection, helper, sb).ToString(); } /// /// Returns the full name of a /// /// The TypeSpec /// Set if output should be compatible with reflection /// Helps print the name /// String builder to use or null /// The full name public static StringBuilder FullNameSB(TypeSpec typeSpec, bool isReflection, IFullNameCreatorHelper helper, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, helper, sb); fnc.CreateFullName(typeSpec); return fnc.sb ?? new StringBuilder(); } /// /// Returns the assembly qualified full name of a /// /// The TypeSpec /// Helps print the name /// String builder to use or null /// The assembly qualified full name public static string AssemblyQualifiedName(TypeSpec typeSpec, IFullNameCreatorHelper helper = null, StringBuilder sb = null) { return AssemblyQualifiedNameSB(typeSpec, helper, sb).ToString(); } /// /// Returns the assembly qualified full name of a /// /// The TypeSpec /// Helps print the name /// String builder to use or null /// The assembly qualified full name public static StringBuilder AssemblyQualifiedNameSB(TypeSpec typeSpec, IFullNameCreatorHelper helper, StringBuilder sb) { var fnc = new FullNameCreator(true, helper, sb); fnc.CreateAssemblyQualifiedName(typeSpec); return fnc.sb ?? new StringBuilder(); } /// /// Returns the assembly where this type is defined /// /// The TypeSpec /// A or null if none found public static IAssembly DefinitionAssembly(TypeSpec typeSpec) { return new FullNameCreator().GetDefinitionAssembly(typeSpec); } /// /// Gets the scope type /// /// The TypeSpec /// The scope type or null if none found public static ITypeDefOrRef ScopeType(TypeSpec typeSpec) { return new FullNameCreator().GetScopeType(typeSpec); } /// /// Gets the scope /// /// The TypeSpec /// The or null if none found public static IScope Scope(TypeSpec typeSpec) { return new FullNameCreator().GetScope(typeSpec); } /// /// Returns the owner module. The type was created from metadata in this module. /// /// The TypeSpec /// A or null if none found public static ModuleDef OwnerModule(TypeSpec typeSpec) { return new FullNameCreator().GetOwnerModule(typeSpec); } /// /// Returns the namespace of a /// /// The type sig /// Set if output should be compatible with reflection /// String builder to use or null /// The namespace public static string Namespace(TypeSig typeSig, bool isReflection, StringBuilder sb = null) { return NamespaceSB(typeSig, isReflection, sb).ToString(); } /// /// Returns the namespace of a /// /// The type sig /// Set if output should be compatible with reflection /// String builder to use or null /// The namespace public static StringBuilder NamespaceSB(TypeSig typeSig, bool isReflection, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, null, sb); fnc.CreateNamespace(typeSig); return fnc.sb ?? new StringBuilder(); } /// /// Returns the name of a /// /// The type sig /// Set if output should be compatible with reflection /// String builder to use or null /// The name public static string Name(TypeSig typeSig, bool isReflection, StringBuilder sb = null) { return NameSB(typeSig, isReflection, sb).ToString(); } /// /// Returns the name of a /// /// The type sig /// Set if output should be compatible with reflection /// String builder to use or null /// The name public static StringBuilder NameSB(TypeSig typeSig, bool isReflection, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, null, sb); fnc.CreateName(typeSig); return fnc.sb ?? new StringBuilder(); } /// /// Returns the full name of a /// /// The type sig /// Set if output should be compatible with reflection /// Helps print the name /// Type generic args or null if none /// Method generic args or null if none /// String builder to use or null /// The full name public static string FullName(TypeSig typeSig, bool isReflection, IFullNameCreatorHelper helper = null, IList typeGenArgs = null, IList methodGenArgs = null, StringBuilder sb = null) { return FullNameSB(typeSig, isReflection, helper, typeGenArgs, methodGenArgs, sb).ToString(); } /// /// Returns the full name of a /// /// The type sig /// Set if output should be compatible with reflection /// Helps print the name /// Type generic args or null if none /// Method generic args or null if none /// String builder to use or null /// The full name public static StringBuilder FullNameSB(TypeSig typeSig, bool isReflection, IFullNameCreatorHelper helper, IList typeGenArgs, IList methodGenArgs, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, helper, sb); if (typeGenArgs != null || methodGenArgs != null) fnc.genericArguments = new GenericArguments(); if (typeGenArgs != null) fnc.genericArguments.PushTypeArgs(typeGenArgs); if (methodGenArgs != null) fnc.genericArguments.PushMethodArgs(methodGenArgs); fnc.CreateFullName(typeSig); return fnc.sb ?? new StringBuilder(); } /// /// Returns the assembly qualified full name of a /// /// The TypeSig /// Helps print the name /// String builder to use or null /// The assembly qualified full name public static string AssemblyQualifiedName(TypeSig typeSig, IFullNameCreatorHelper helper = null, StringBuilder sb = null) { return AssemblyQualifiedNameSB(typeSig, helper, sb).ToString(); } /// /// Returns the assembly qualified full name of a /// /// The TypeSig /// Helps print the name /// String builder to use or null /// The assembly qualified full name public static StringBuilder AssemblyQualifiedNameSB(TypeSig typeSig, IFullNameCreatorHelper helper, StringBuilder sb) { var fnc = new FullNameCreator(true, helper, sb); fnc.CreateAssemblyQualifiedName(typeSig); return fnc.sb ?? new StringBuilder(); } /// /// Returns the assembly where this type is defined /// /// The TypeSig /// A or null if none found public static IAssembly DefinitionAssembly(TypeSig typeSig) { return new FullNameCreator().GetDefinitionAssembly(typeSig); } /// /// Gets the scope /// /// The TypeSig /// The or null if none found public static IScope Scope(TypeSig typeSig) { return new FullNameCreator().GetScope(typeSig); } /// /// Gets the scope type /// /// The TypeSig /// The scope type or null if none found public static ITypeDefOrRef ScopeType(TypeSig typeSig) { return new FullNameCreator().GetScopeType(typeSig); } /// /// Returns the owner module. The type was created from metadata in this module. /// /// The TypeSig /// A or null if none found public static ModuleDef OwnerModule(TypeSig typeSig) { return new FullNameCreator().GetOwnerModule(typeSig); } /// /// Returns the namespace of a /// /// The ExportedType /// Set if output should be compatible with reflection /// String builder to use or null /// The namespace public static string Namespace(ExportedType exportedType, bool isReflection, StringBuilder sb = null) { return NamespaceSB(exportedType, isReflection, sb).ToString(); } /// /// Returns the namespace of a /// /// The ExportedType /// Set if output should be compatible with reflection /// String builder to use or null /// The namespace public static StringBuilder NamespaceSB(ExportedType exportedType, bool isReflection, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, null, sb); fnc.CreateNamespace(exportedType); return fnc.sb ?? new StringBuilder(); } /// /// Returns the name of a /// /// The ExportedType /// Set if output should be compatible with reflection /// String builder to use or null /// The name public static string Name(ExportedType exportedType, bool isReflection, StringBuilder sb = null) { return NameSB(exportedType, isReflection, sb).ToString(); } /// /// Returns the name of a /// /// The ExportedType /// Set if output should be compatible with reflection /// String builder to use or null /// The name public static StringBuilder NameSB(ExportedType exportedType, bool isReflection, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, null, sb); fnc.CreateName(exportedType); return fnc.sb ?? new StringBuilder(); } /// /// Returns the full name of a /// /// The ExportedType /// Set if output should be compatible with reflection /// Helps print the name /// String builder to use or null /// The full name public static string FullName(ExportedType exportedType, bool isReflection, IFullNameCreatorHelper helper = null, StringBuilder sb = null) { return FullNameSB(exportedType, isReflection, helper, sb).ToString(); } /// /// Returns the full name of a /// /// The ExportedType /// Set if output should be compatible with reflection /// Helps print the name /// String builder to use or null /// The full name public static StringBuilder FullNameSB(ExportedType exportedType, bool isReflection, IFullNameCreatorHelper helper, StringBuilder sb) { var fnc = new FullNameCreator(isReflection, helper, sb); fnc.CreateFullName(exportedType); return fnc.sb ?? new StringBuilder(); } /// /// Returns the assembly qualified full name of a /// /// The ExportedType /// Helps print the name /// String builder to use or null /// The assembly qualified full name public static string AssemblyQualifiedName(ExportedType exportedType, IFullNameCreatorHelper helper = null, StringBuilder sb = null) { return AssemblyQualifiedNameSB(exportedType, helper, sb).ToString(); } /// /// Returns the assembly qualified full name of a /// /// The ExportedType /// Helps print the name /// String builder to use or null /// The assembly qualified full name public static StringBuilder AssemblyQualifiedNameSB(ExportedType exportedType, IFullNameCreatorHelper helper, StringBuilder sb) { var fnc = new FullNameCreator(true, helper, sb); fnc.CreateAssemblyQualifiedName(exportedType); return fnc.sb ?? new StringBuilder(); } /// /// Returns the assembly where this type is defined /// /// The ExportedType /// A or null if none found public static IAssembly DefinitionAssembly(ExportedType exportedType) { return new FullNameCreator().GetDefinitionAssembly(exportedType); } /// /// Gets the scope type /// /// The ExportedType /// The scope type or null if none found public static ITypeDefOrRef ScopeType(ExportedType exportedType) { return new FullNameCreator().GetScopeType(exportedType); } /// /// Gets the scope /// /// The ExportedType /// The or null if none found public static IScope Scope(ExportedType exportedType) { return new FullNameCreator().GetScope(exportedType); } /// /// Returns the owner module. The type was created from metadata in this module. /// /// The ExportedType /// A or null if none found public static ModuleDef OwnerModule(ExportedType exportedType) { return new FullNameCreator().GetOwnerModule(exportedType); } string Result { get { return sb == null ? null : sb.ToString(); } } FullNameCreator(bool isReflection, IFullNameCreatorHelper helper, StringBuilder sb) { this.sb = sb ?? new StringBuilder(); this.isReflection = isReflection; this.helper = helper; this.genericArguments = null; this.recursionCounter = new RecursionCounter(); } bool MustUseAssemblyName(IType type) { if (helper == null) return true; return helper.MustUseAssemblyName(GetDefinitionType(type)); } IType GetDefinitionType(IType type) { if (!recursionCounter.Increment()) return type; TypeSpec ts = type as TypeSpec; if (ts != null) type = ts.TypeSig; TypeSig sig = type as TypeSig; if (sig != null) { TypeDefOrRefSig tdr; GenericInstSig gis; if ((tdr = sig as TypeDefOrRefSig) != null) type = GetDefinitionType(tdr.TypeDefOrRef); else if ((gis = sig as GenericInstSig) != null) type = GetDefinitionType(gis.GenericType); else type = GetDefinitionType(sig.Next); } recursionCounter.Decrement(); return type; } void CreateFullName(ITypeDefOrRef typeDefOrRef) { if (typeDefOrRef is TypeRef) CreateFullName((TypeRef)typeDefOrRef); else if (typeDefOrRef is TypeDef) CreateFullName((TypeDef)typeDefOrRef); else if (typeDefOrRef is TypeSpec) CreateFullName((TypeSpec)typeDefOrRef); else sb.Append(NULLVALUE); } void CreateNamespace(ITypeDefOrRef typeDefOrRef) { if (typeDefOrRef is TypeRef) CreateNamespace((TypeRef)typeDefOrRef); else if (typeDefOrRef is TypeDef) CreateNamespace((TypeDef)typeDefOrRef); else if (typeDefOrRef is TypeSpec) CreateNamespace((TypeSpec)typeDefOrRef); else sb.Append(NULLVALUE); } void CreateName(ITypeDefOrRef typeDefOrRef) { if (typeDefOrRef is TypeRef) CreateName((TypeRef)typeDefOrRef); else if (typeDefOrRef is TypeDef) CreateName((TypeDef)typeDefOrRef); else if (typeDefOrRef is TypeSpec) CreateName((TypeSpec)typeDefOrRef); else sb.Append(NULLVALUE); } void CreateAssemblyQualifiedName(ITypeDefOrRef typeDefOrRef) { if (typeDefOrRef is TypeRef) CreateAssemblyQualifiedName((TypeRef)typeDefOrRef); else if (typeDefOrRef is TypeDef) CreateAssemblyQualifiedName((TypeDef)typeDefOrRef); else if (typeDefOrRef is TypeSpec) CreateAssemblyQualifiedName((TypeSpec)typeDefOrRef); else sb.Append(NULLVALUE); } void CreateAssemblyQualifiedName(TypeRef typeRef) { if (typeRef == null) { sb.Append(NULLVALUE); return; } if (!recursionCounter.Increment()) { sb.Append(RECURSION_ERROR_RESULT_STRING); return; } CreateFullName(typeRef); if (MustUseAssemblyName(typeRef)) AddAssemblyName(GetDefinitionAssembly(typeRef)); recursionCounter.Decrement(); } void CreateFullName(TypeRef typeRef) { if (typeRef == null) { sb.Append(NULLVALUE); return; } if (!recursionCounter.Increment()) { sb.Append(RECURSION_ERROR_RESULT_STRING); return; } var declaringTypeRef = typeRef.ResolutionScope as TypeRef; if (declaringTypeRef != null) { CreateFullName(declaringTypeRef); AddNestedTypeSeparator(); } if (AddNamespace(typeRef.Namespace)) sb.Append('.'); AddName(typeRef.Name); recursionCounter.Decrement(); } void CreateNamespace(TypeRef typeRef) { if (typeRef == null) { sb.Append(NULLVALUE); return; } AddNamespace(typeRef.Namespace); } void CreateName(TypeRef typeRef) { if (typeRef == null) { sb.Append(NULLVALUE); return; } AddName(typeRef.Name); } void CreateAssemblyQualifiedName(TypeDef typeDef) { if (typeDef == null) { sb.Append(NULLVALUE); return; } if (!recursionCounter.Increment()) { sb.Append(RECURSION_ERROR_RESULT_STRING); return; } CreateFullName(typeDef); if (MustUseAssemblyName(typeDef)) AddAssemblyName(GetDefinitionAssembly(typeDef)); recursionCounter.Decrement(); } void CreateFullName(TypeDef typeDef) { if (typeDef == null) { sb.Append(NULLVALUE); return; } if (!recursionCounter.Increment()) { sb.Append(RECURSION_ERROR_RESULT_STRING); return; } var declaringTypeDef = typeDef.DeclaringType; if (declaringTypeDef != null) { CreateFullName(declaringTypeDef); AddNestedTypeSeparator(); } if (AddNamespace(typeDef.Namespace)) sb.Append('.'); AddName(typeDef.Name); recursionCounter.Decrement(); } void CreateNamespace(TypeDef typeDef) { if (typeDef == null) { sb.Append(NULLVALUE); return; } AddNamespace(typeDef.Namespace); } void CreateName(TypeDef typeDef) { if (typeDef == null) { sb.Append(NULLVALUE); return; } AddName(typeDef.Name); } void CreateAssemblyQualifiedName(TypeSpec typeSpec) { if (typeSpec == null) { sb.Append(NULLVALUE); return; } CreateAssemblyQualifiedName(typeSpec.TypeSig); } void CreateFullName(TypeSpec typeSpec) { if (typeSpec == null) { sb.Append(NULLVALUE); return; } CreateFullName(typeSpec.TypeSig); } void CreateNamespace(TypeSpec typeSpec) { if (typeSpec == null) { sb.Append(NULLVALUE); return; } CreateNamespace(typeSpec.TypeSig); } void CreateName(TypeSpec typeSpec) { if (typeSpec == null) { sb.Append(NULLVALUE); return; } CreateName(typeSpec.TypeSig); } void CreateAssemblyQualifiedName(TypeSig typeSig) { if (typeSig == null) { sb.Append(NULLVALUE); return; } if (!recursionCounter.Increment()) { sb.Append(RECURSION_ERROR_RESULT_STRING); return; } CreateFullName(typeSig); if (MustUseAssemblyName(typeSig)) AddAssemblyName(GetDefinitionAssembly(typeSig)); recursionCounter.Decrement(); } void CreateFullName(TypeSig typeSig) { CreateTypeSigName(typeSig, TYPESIG_NAMESPACE | TYPESIG_NAME); } void CreateNamespace(TypeSig typeSig) { CreateTypeSigName(typeSig, TYPESIG_NAMESPACE); } void CreateName(TypeSig typeSig) { CreateTypeSigName(typeSig, TYPESIG_NAME); } TypeSig ReplaceGenericArg(TypeSig typeSig) { if (genericArguments == null) return typeSig; var newTypeSig = genericArguments.Resolve(typeSig); if (newTypeSig != typeSig) genericArguments = null; return newTypeSig; } const int TYPESIG_NAMESPACE = 1; const int TYPESIG_NAME = 2; void CreateTypeSigName(TypeSig typeSig, int flags) { if (typeSig == null) { sb.Append(NULLVALUE); return; } if (!recursionCounter.Increment()) { sb.Append(RECURSION_ERROR_RESULT_STRING); return; } var old = genericArguments; typeSig = ReplaceGenericArg(typeSig); bool createNamespace = (flags & TYPESIG_NAMESPACE) != 0; bool createName = (flags & TYPESIG_NAME) != 0; switch (typeSig.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: case ElementType.ValueType: case ElementType.Class: if (createNamespace && createName) CreateFullName(((TypeDefOrRefSig)typeSig).TypeDefOrRef); else if (createNamespace) CreateNamespace(((TypeDefOrRefSig)typeSig).TypeDefOrRef); else if (createName) CreateName(((TypeDefOrRefSig)typeSig).TypeDefOrRef); break; case ElementType.Ptr: CreateTypeSigName(typeSig.Next, flags); if (createName) sb.Append('*'); break; case ElementType.ByRef: CreateTypeSigName(typeSig.Next, flags); if (createName) sb.Append('&'); break; case ElementType.Array: CreateTypeSigName(typeSig.Next, flags); if (createName) { var arraySig = (ArraySig)typeSig; sb.Append('['); uint rank = arraySig.Rank; if (rank == 0) sb.Append(""); // Not allowed else if (rank == 1) sb.Append('*'); else for (int i = 0; i < (int)rank; i++) { if (i != 0) sb.Append(','); if (!isReflection) { const int NO_LOWER = int.MinValue; const uint NO_SIZE = uint.MaxValue; int lower = arraySig.LowerBounds.Get(i, NO_LOWER); uint size = arraySig.Sizes.Get(i, NO_SIZE); if (lower != NO_LOWER) { sb.Append(lower); sb.Append(".."); if (size != NO_SIZE) sb.Append(lower + (int)size - 1); else sb.Append('.'); } } } sb.Append(']'); } break; case ElementType.SZArray: CreateTypeSigName(typeSig.Next, flags); if (createName) sb.Append("[]"); break; case ElementType.CModReqd: CreateTypeSigName(typeSig.Next, flags); if (!isReflection && createName) { sb.Append(" modreq("); if (createNamespace) CreateFullName(((ModifierSig)typeSig).Modifier); else CreateName(((ModifierSig)typeSig).Modifier); sb.Append(")"); } break; case ElementType.CModOpt: CreateTypeSigName(typeSig.Next, flags); if (!isReflection && createName) { sb.Append(" modopt("); if (createNamespace) CreateFullName(((ModifierSig)typeSig).Modifier); else CreateName(((ModifierSig)typeSig).Modifier); sb.Append(")"); } break; case ElementType.Pinned: CreateTypeSigName(typeSig.Next, flags); break; case ElementType.ValueArray: CreateTypeSigName(typeSig.Next, flags); if (createName) { var valueArraySig = (ValueArraySig)typeSig; sb.Append(" ValueArray("); sb.Append(valueArraySig.Size); sb.Append(')'); } break; case ElementType.Module: CreateTypeSigName(typeSig.Next, flags); if (createName) { var moduleSig = (ModuleSig)typeSig; sb.Append(" Module("); sb.Append(moduleSig.Index); sb.Append(')'); } break; case ElementType.GenericInst: var genericInstSig = (GenericInstSig)typeSig; var typeGenArgs = genericInstSig.GenericArguments; CreateTypeSigName(genericInstSig.GenericType, flags); if (createNamespace && createName) { if (isReflection) { sb.Append('['); int i = -1; foreach (var genArg in typeGenArgs.GetSafeEnumerable()) { i++; if (i != 0) sb.Append(','); bool mustWriteAssembly = MustUseAssemblyName(genArg); if (mustWriteAssembly) sb.Append('['); CreateFullName(genArg); if (mustWriteAssembly) { sb.Append(", "); var asm = GetDefinitionAssembly(genArg); if (asm == null) sb.Append(NULLVALUE); else sb.Append(EscapeAssemblyName(GetAssemblyName(asm))); sb.Append(']'); } } sb.Append(']'); } else { sb.Append('<'); int i = -1; foreach (var genArg in typeGenArgs.GetSafeEnumerable()) { i++; if (i != 0) sb.Append(','); CreateFullName(genArg); } sb.Append('>'); } } break; case ElementType.Var: case ElementType.MVar: if (createName) { var gs = (GenericSig)typeSig; var gp = gs.GenericParam; if (gp == null || !AddName(gp.Name)) { sb.Append(gs.IsMethodVar ? "!!" : "!"); sb.Append(gs.Number); } } break; case ElementType.FnPtr: if (createName) { if (isReflection) sb.Append("(fnptr)"); else CreateMethodFullName(null, null, ((FnPtrSig)typeSig).MethodSig, null); } break; case ElementType.Sentinel: break; case ElementType.End: case ElementType.R: case ElementType.Internal: default: break; } genericArguments = old; recursionCounter.Decrement(); } void CreateAssemblyQualifiedName(ExportedType exportedType) { if (exportedType == null) { sb.Append(NULLVALUE); return; } if (!recursionCounter.Increment()) { sb.Append(RECURSION_ERROR_RESULT_STRING); return; } CreateFullName(exportedType); if (MustUseAssemblyName(exportedType)) AddAssemblyName(GetDefinitionAssembly(exportedType)); recursionCounter.Decrement(); } void CreateFullName(ExportedType exportedType) { if (exportedType == null) { sb.Append(NULLVALUE); return; } if (!recursionCounter.Increment()) { sb.Append(RECURSION_ERROR_RESULT_STRING); return; } var declaringExportedType = exportedType.Implementation as ExportedType; if (declaringExportedType != null) { CreateFullName(declaringExportedType); AddNestedTypeSeparator(); } if (AddNamespace(exportedType.TypeNamespace)) sb.Append('.'); AddName(exportedType.TypeName); recursionCounter.Decrement(); } void CreateNamespace(ExportedType exportedType) { if (exportedType == null) { sb.Append(NULLVALUE); return; } AddNamespace(exportedType.TypeNamespace); } void CreateName(ExportedType exportedType) { if (exportedType == null) { sb.Append(NULLVALUE); return; } AddName(exportedType.TypeName); } static string GetAssemblyName(IAssembly assembly) { var pk = assembly.PublicKeyOrToken; if (pk is PublicKey) pk = ((PublicKey)pk).Token; return Utils.GetAssemblyNameString(EscapeAssemblyName(assembly.Name), assembly.Version, assembly.Culture, pk, assembly.Attributes); } static string EscapeAssemblyName(UTF8String asmSimplName) { return EscapeAssemblyName(UTF8String.ToSystemString(asmSimplName)); } static string EscapeAssemblyName(string asmSimplName) { var sb = new StringBuilder(asmSimplName.Length); foreach (var c in asmSimplName) { if (c == ']') sb.Append('\\'); sb.Append(c); } return sb.ToString(); } void AddNestedTypeSeparator() { if (isReflection) sb.Append('+'); else sb.Append('/'); } bool AddNamespace(UTF8String @namespace) { if (UTF8String.IsNullOrEmpty(@namespace)) return false; AddIdentifier(@namespace.String); return true; } bool AddName(UTF8String name) { if (UTF8String.IsNullOrEmpty(name)) return false; AddIdentifier(name.String); return true; } void AddAssemblyName(IAssembly assembly) { sb.Append(", "); if (assembly == null) sb.Append(NULLVALUE); else { var pkt = assembly.PublicKeyOrToken; if (pkt is PublicKey) pkt = ((PublicKey)pkt).Token; sb.Append(Utils.GetAssemblyNameString(assembly.Name, assembly.Version, assembly.Culture, pkt, assembly.Attributes)); } } void AddIdentifier(string id) { if (isReflection) { // Periods are not escaped by Reflection, even if they're part of a type name. foreach (var c in id) { switch (c) { case ',': case '+': case '&': case '*': case '[': case ']': case '\\': sb.Append('\\'); break; } sb.Append(c); } } else sb.Append(id); } IAssembly GetDefinitionAssembly(ITypeDefOrRef typeDefOrRef) { var tr = typeDefOrRef as TypeRef; if (tr != null) return GetDefinitionAssembly(tr); var td = typeDefOrRef as TypeDef; if (td != null) return GetDefinitionAssembly(td); var ts = typeDefOrRef as TypeSpec; if (ts != null) return GetDefinitionAssembly(ts); return null; } IScope GetScope(ITypeDefOrRef typeDefOrRef) { var tr = typeDefOrRef as TypeRef; if (tr != null) return GetScope(tr); var td = typeDefOrRef as TypeDef; if (td != null) return td.Scope; var ts = typeDefOrRef as TypeSpec; if (ts != null) return GetScope(ts); return null; } ITypeDefOrRef GetScopeType(ITypeDefOrRef typeDefOrRef) { var tr = typeDefOrRef as TypeRef; if (tr != null) return tr; var td = typeDefOrRef as TypeDef; if (td != null) return td; var ts = typeDefOrRef as TypeSpec; if (ts != null) return GetScopeType(ts); return null; } ModuleDef GetOwnerModule(ITypeDefOrRef typeDefOrRef) { var tr = typeDefOrRef as TypeRef; if (tr != null) return GetOwnerModule(tr); var td = typeDefOrRef as TypeDef; if (td != null) return GetOwnerModule(td); var ts = typeDefOrRef as TypeSpec; if (ts != null) return GetOwnerModule(ts); return null; } IAssembly GetDefinitionAssembly(TypeRef typeRef) { if (typeRef == null) return null; if (!recursionCounter.Increment()) return null; IAssembly result; var scope = typeRef.ResolutionScope; if (scope == null) result = null; //TODO: Check ownerModule's ExportedType table else if (scope is TypeRef) result = GetDefinitionAssembly((TypeRef)scope); else if (scope is AssemblyRef) result = (AssemblyRef)scope; else if (scope is ModuleRef) { var ownerModule = GetOwnerModule(typeRef); result = ownerModule == null ? null : ownerModule.Assembly; } else if (scope is ModuleDef) result = ((ModuleDef)scope).Assembly; else result = null; // Should never be reached recursionCounter.Decrement(); return result; } IScope GetScope(TypeRef typeRef) { if (typeRef == null) return null; if (!recursionCounter.Increment()) return null; IScope result; TypeRef tr; AssemblyRef asmRef; ModuleRef modRef; ModuleDef modDef; var scope = typeRef.ResolutionScope; if (scope == null) result = null; //TODO: Check ownerModule's ExportedType table else if ((tr = scope as TypeRef) != null) result = GetScope(tr); else if ((asmRef = scope as AssemblyRef) != null) result = asmRef; else if ((modRef = scope as ModuleRef) != null) result = modRef; else if ((modDef = scope as ModuleDef) != null) result = modDef; else result = null; // Should never be reached recursionCounter.Decrement(); return result; } ModuleDef GetOwnerModule(TypeRef typeRef) { if (typeRef == null) return null; return typeRef.Module; } IAssembly GetDefinitionAssembly(TypeDef typeDef) { var ownerModule = GetOwnerModule(typeDef); return ownerModule == null ? null : ownerModule.Assembly; } ModuleDef GetOwnerModule(TypeDef typeDef) { if (typeDef == null) return null; ModuleDef result = null; for (int i = recursionCounter.Counter; i < RecursionCounter.MAX_RECURSION_COUNT; i++) { var declaringType = typeDef.DeclaringType; if (declaringType == null) { result = typeDef.Module2; break; } typeDef = declaringType; } return result; } IAssembly GetDefinitionAssembly(TypeSpec typeSpec) { if (typeSpec == null) return null; return GetDefinitionAssembly(typeSpec.TypeSig); } IScope GetScope(TypeSpec typeSpec) { if (typeSpec == null) return null; return GetScope(typeSpec.TypeSig); } ITypeDefOrRef GetScopeType(TypeSpec typeSpec) { if (typeSpec == null) return null; return GetScopeType(typeSpec.TypeSig); } ModuleDef GetOwnerModule(TypeSpec typeSpec) { if (typeSpec == null) return null; return GetOwnerModule(typeSpec.TypeSig); } IAssembly GetDefinitionAssembly(TypeSig typeSig) { if (typeSig == null) return null; if (!recursionCounter.Increment()) return null; IAssembly result; var old = genericArguments; typeSig = ReplaceGenericArg(typeSig); switch (typeSig.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: case ElementType.ValueType: case ElementType.Class: result = GetDefinitionAssembly(((TypeDefOrRefSig)typeSig).TypeDefOrRef); break; case ElementType.Ptr: case ElementType.ByRef: case ElementType.Array: case ElementType.SZArray: case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Pinned: case ElementType.ValueArray: case ElementType.Module: result = GetDefinitionAssembly(typeSig.Next); break; case ElementType.GenericInst: var genericInstSig = (GenericInstSig)typeSig; var genericType = genericInstSig.GenericType; result = GetDefinitionAssembly(genericType == null ? null : genericType.TypeDefOrRef); break; case ElementType.Var: case ElementType.MVar: case ElementType.FnPtr: case ElementType.Sentinel: case ElementType.End: case ElementType.R: case ElementType.Internal: default: result = null; break; } genericArguments = old; recursionCounter.Decrement(); return result; } ITypeDefOrRef GetScopeType(TypeSig typeSig) { if (typeSig == null) return null; if (!recursionCounter.Increment()) return null; ITypeDefOrRef result; var old = genericArguments; typeSig = ReplaceGenericArg(typeSig); switch (typeSig.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: case ElementType.ValueType: case ElementType.Class: result = GetScopeType(((TypeDefOrRefSig)typeSig).TypeDefOrRef); break; case ElementType.Ptr: case ElementType.ByRef: case ElementType.Array: case ElementType.SZArray: case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Pinned: case ElementType.ValueArray: case ElementType.Module: result = GetScopeType(typeSig.Next); break; case ElementType.GenericInst: var genericInstSig = (GenericInstSig)typeSig; var genericType = genericInstSig.GenericType; result = GetScopeType(genericType == null ? null : genericType.TypeDefOrRef); break; case ElementType.Var: case ElementType.MVar: case ElementType.FnPtr: case ElementType.Sentinel: case ElementType.End: case ElementType.R: case ElementType.Internal: default: result = null; break; } genericArguments = old; recursionCounter.Decrement(); return result; } IScope GetScope(TypeSig typeSig) { if (typeSig == null) return null; if (!recursionCounter.Increment()) return null; IScope result; var old = genericArguments; typeSig = ReplaceGenericArg(typeSig); switch (typeSig.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: case ElementType.ValueType: case ElementType.Class: result = GetScope(((TypeDefOrRefSig)typeSig).TypeDefOrRef); break; case ElementType.Ptr: case ElementType.ByRef: case ElementType.Array: case ElementType.SZArray: case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Pinned: case ElementType.ValueArray: case ElementType.Module: result = GetScope(typeSig.Next); break; case ElementType.GenericInst: var genericInstSig = (GenericInstSig)typeSig; var genericType = genericInstSig.GenericType; result = GetScope(genericType == null ? null : genericType.TypeDefOrRef); break; case ElementType.Var: case ElementType.MVar: case ElementType.FnPtr: case ElementType.Sentinel: case ElementType.End: case ElementType.R: case ElementType.Internal: default: result = null; break; } genericArguments = old; recursionCounter.Decrement(); return result; } ModuleDef GetOwnerModule(TypeSig typeSig) { if (typeSig == null) return null; if (!recursionCounter.Increment()) return null; ModuleDef result; var old = genericArguments; typeSig = ReplaceGenericArg(typeSig); switch (typeSig.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: case ElementType.ValueType: case ElementType.Class: result = GetOwnerModule(((TypeDefOrRefSig)typeSig).TypeDefOrRef); break; case ElementType.Ptr: case ElementType.ByRef: case ElementType.Array: case ElementType.SZArray: case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Pinned: case ElementType.ValueArray: case ElementType.Module: result = GetOwnerModule(typeSig.Next); break; case ElementType.GenericInst: var genericInstSig = (GenericInstSig)typeSig; var genericType = genericInstSig.GenericType; result = GetOwnerModule(genericType == null ? null : genericType.TypeDefOrRef); break; case ElementType.Var: case ElementType.MVar: case ElementType.FnPtr: case ElementType.Sentinel: case ElementType.End: case ElementType.R: case ElementType.Internal: default: result = null; break; } genericArguments = old; recursionCounter.Decrement(); return result; } IAssembly GetDefinitionAssembly(ExportedType exportedType) { if (exportedType == null) return null; if (!recursionCounter.Increment()) return null; IAssembly result; ExportedType et; AssemblyRef asmRef; var scope = exportedType.Implementation; if ((et = scope as ExportedType) != null) result = GetDefinitionAssembly(et); else if ((asmRef = scope as AssemblyRef) != null) result = asmRef; else if (scope is FileDef) { var ownerModule = GetOwnerModule(exportedType); result = ownerModule == null ? null : ownerModule.Assembly; } else result = null; recursionCounter.Decrement(); return result; } ITypeDefOrRef GetScopeType(ExportedType exportedType) { return null; } IScope GetScope(ExportedType exportedType) { if (exportedType == null) return null; if (!recursionCounter.Increment()) return null; IScope result; ExportedType et; AssemblyRef asmRef; FileDef file; var scope = exportedType.Implementation; if ((et = scope as ExportedType) != null) result = GetScope(et); else if ((asmRef = scope as AssemblyRef) != null) result = asmRef; else if ((file = scope as FileDef) != null) { var ownerModule = GetOwnerModule(exportedType); //TODO: Not all modules' names are equal to the name in FileDef.Name var modRef = new ModuleRefUser(ownerModule, file.Name); if (ownerModule != null) ownerModule.UpdateRowId(modRef); result = modRef; } else result = null; recursionCounter.Decrement(); return result; } ModuleDef GetOwnerModule(ExportedType exportedType) { if (exportedType == null) return null; return exportedType.Module; } void CreateFieldFullName(string declaringType, string name, FieldSig fieldSig) { CreateFullName(fieldSig == null ? null : fieldSig.Type); sb.Append(' '); if (declaringType != null) { sb.Append(declaringType); sb.Append("::"); } if (name != null) sb.Append(name); } void CreateMethodFullName(string declaringType, string name, MethodBaseSig methodSig, MethodDef gppMethod) { if (methodSig == null) { sb.Append(NULLVALUE); return; } CreateFullName(methodSig.RetType); sb.Append(' '); if (declaringType != null) { sb.Append(declaringType); sb.Append("::"); } if (name != null) sb.Append(name); if (methodSig.Generic) { sb.Append('<'); uint genParamCount = methodSig.GenParamCount; for (uint i = 0; i < genParamCount; i++) { if (i != 0) sb.Append(','); CreateFullName(new GenericMVar(i, gppMethod)); } sb.Append('>'); } sb.Append('('); int count = PrintMethodArgList(methodSig.Params, false, false); PrintMethodArgList(methodSig.ParamsAfterSentinel, count > 0, true); sb.Append(')'); } int PrintMethodArgList(IEnumerable args, bool hasPrintedArgs, bool isAfterSentinel) { if (args == null) return 0; if (isAfterSentinel) { if (hasPrintedArgs) sb.Append(','); sb.Append("..."); hasPrintedArgs = true; } int count = 0; foreach (var arg in args.GetSafeEnumerable()) { count++; if (hasPrintedArgs) sb.Append(','); CreateFullName(arg); hasPrintedArgs = true; } return count; } void CreatePropertyFullName(string declaringType, UTF8String name, CallingConventionSig propertySig) { CreateMethodFullName(declaringType, UTF8String.ToSystemString(name), propertySig as MethodBaseSig, null); } void CreateEventFullName(string declaringType, UTF8String name, ITypeDefOrRef typeDefOrRef) { CreateFullName(typeDefOrRef); sb.Append(' '); if (declaringType != null) { sb.Append(declaringType); sb.Append("::"); } if (!UTF8String.IsNull(name)) sb.Append(UTF8String.ToSystemString(name)); } /// public override string ToString() { return Result; } } } dnlib-2.1_VS2010/src/DotNet/GenericArguments.cs000066400000000000000000000072041325033663500211450ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; namespace dnlib.DotNet { struct GenericArgumentsStack { readonly List> argsStack; readonly bool isTypeVar; /// /// Constructor /// /// true if it's for generic types, false if generic methods public GenericArgumentsStack(bool isTypeVar) { this.argsStack = new List>(); this.isTypeVar = isTypeVar; } /// /// Pushes generic arguments /// /// The generic arguments public void Push(IList args) { argsStack.Add(args); } /// /// Pops generic arguments /// /// The popped generic arguments public IList Pop() { int index = argsStack.Count - 1; var result = argsStack[index]; argsStack.RemoveAt(index); return result; } /// /// Resolves a generic argument /// /// Generic variable number /// A or null if none was found public TypeSig Resolve(uint number) { TypeSig result = null; for (int i = argsStack.Count - 1; i >= 0; i--) { var args = argsStack[i]; if (number >= args.Count) return null; var typeSig = args[(int)number]; var gvar = typeSig as GenericSig; if (gvar == null || gvar.IsTypeVar != isTypeVar) return typeSig; result = gvar; number = gvar.Number; } return result; } } /// /// Replaces generic type/method var with its generic argument /// public sealed class GenericArguments { GenericArgumentsStack typeArgsStack = new GenericArgumentsStack(true); GenericArgumentsStack methodArgsStack = new GenericArgumentsStack(false); /// /// Pushes generic arguments /// /// The generic arguments public void PushTypeArgs(IList typeArgs) { typeArgsStack.Push(typeArgs); } /// /// Pops generic arguments /// /// The popped generic arguments public IList PopTypeArgs() { return typeArgsStack.Pop(); } /// /// Pushes generic arguments /// /// The generic arguments public void PushMethodArgs(IList methodArgs) { methodArgsStack.Push(methodArgs); } /// /// Pops generic arguments /// /// The popped generic arguments public IList PopMethodArgs() { return methodArgsStack.Pop(); } /// /// Replaces a generic type/method var with its generic argument (if any). If /// isn't a generic type/method var or if it can't /// be resolved, it itself is returned. Else the resolved type is returned. /// /// Type signature /// New which is never null unless /// is null public TypeSig Resolve(TypeSig typeSig) { if (typeSig == null) return null; var sig = typeSig; var genericMVar = sig as GenericMVar; if (genericMVar != null) { var newSig = methodArgsStack.Resolve(genericMVar.Number); if (newSig == null || newSig == sig) return sig; return newSig; } var genericVar = sig as GenericVar; if (genericVar != null) { var newSig = typeArgsStack.Resolve(genericVar.Number); if (newSig == null || newSig == sig) return sig; return newSig; } return sig; } } } dnlib-2.1_VS2010/src/DotNet/GenericParam.cs000066400000000000000000000375011325033663500202430ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.Threading; using dnlib.Utils; using dnlib.DotNet.MD; using dnlib.Threading; using dnlib.DotNet.Pdb; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the GenericParam table /// [DebuggerDisplay("{Name.String}")] public abstract class GenericParam : IHasCustomAttribute, IHasCustomDebugInformation, IMemberDef, IListListener { /// /// The row id in its table /// protected uint rid; /// public MDToken MDToken { get { return new MDToken(Table.GenericParam, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 19; } } /// /// Gets the owner type/method /// public ITypeOrMethodDef Owner { get { return owner; } internal set { owner = value; } } /// protected ITypeOrMethodDef owner; /// /// Gets the declaring type or null if none or if is /// not a /// public TypeDef DeclaringType { get { return owner as TypeDef; } } /// ITypeDefOrRef IMemberRef.DeclaringType { get { return owner as TypeDef; } } /// /// Gets the declaring method or null if none or if is /// not a /// public MethodDef DeclaringMethod { get { return owner as MethodDef; } } /// /// From column GenericParam.Number /// public ushort Number { get { return number; } set { number = value; } } /// protected ushort number; /// /// From column GenericParam.Flags /// public GenericParamAttributes Flags { get { return (GenericParamAttributes)attributes; } set { attributes = (int)value; } } /// Attributes protected int attributes; /// /// From column GenericParam.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// From column GenericParam.Kind (v1.1 only) /// public ITypeDefOrRef Kind { get { return kind; } set { kind = value; } } /// protected ITypeDefOrRef kind; /// /// Gets the generic param constraints /// public ThreadSafe.IList GenericParamConstraints { get { if (genericParamConstraints == null) InitializeGenericParamConstraints(); return genericParamConstraints; } } /// protected LazyList genericParamConstraints; /// Initializes protected virtual void InitializeGenericParamConstraints() { Interlocked.CompareExchange(ref genericParamConstraints, new LazyList(this), null); } /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 19; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// /// true if is not empty /// public bool HasGenericParamConstraints { get { return GenericParamConstraints.Count > 0; } } /// public ModuleDef Module { get { var dt = owner; return dt == null ? null : dt.Module; } } /// public string FullName { get { return UTF8String.ToSystemStringOrEmpty(name); } } bool IIsTypeOrMethod.IsType { get { return false; } } bool IIsTypeOrMethod.IsMethod { get { return false; } } bool IMemberRef.IsField { get { return false; } } bool IMemberRef.IsTypeSpec { get { return false; } } bool IMemberRef.IsTypeRef { get { return false; } } bool IMemberRef.IsTypeDef { get { return false; } } bool IMemberRef.IsMethodSpec { get { return false; } } bool IMemberRef.IsMethodDef { get { return false; } } bool IMemberRef.IsMemberRef { get { return false; } } bool IMemberRef.IsFieldDef { get { return false; } } bool IMemberRef.IsPropertyDef { get { return false; } } bool IMemberRef.IsEventDef { get { return false; } } bool IMemberRef.IsGenericParam { get { return true; } } /// /// Modify property: = /// ( & ) | . /// /// Value to AND /// Value to OR void ModifyAttributes(GenericParamAttributes andMask, GenericParamAttributes 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 attributes = (attributes & (int)andMask) | (int)orMask; #endif } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyAttributes(bool set, GenericParamAttributes 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 variance (non, contra, co) /// public GenericParamAttributes Variance { get { return (GenericParamAttributes)attributes & GenericParamAttributes.VarianceMask; } set { ModifyAttributes(~GenericParamAttributes.VarianceMask, value & GenericParamAttributes.VarianceMask); } } /// /// true if is set /// public bool IsNonVariant { get { return Variance == GenericParamAttributes.NonVariant; } } /// /// true if is set /// public bool IsCovariant { get { return Variance == GenericParamAttributes.Covariant; } } /// /// true if is set /// public bool IsContravariant { get { return Variance == GenericParamAttributes.Contravariant; } } /// /// Gets/sets the special constraint /// public GenericParamAttributes SpecialConstraint { get { return (GenericParamAttributes)attributes & GenericParamAttributes.SpecialConstraintMask; } set { ModifyAttributes(~GenericParamAttributes.SpecialConstraintMask, value & GenericParamAttributes.SpecialConstraintMask); } } /// /// true if there are no special constraints /// public bool HasNoSpecialConstraint { get { return ((GenericParamAttributes)attributes & GenericParamAttributes.SpecialConstraintMask) == GenericParamAttributes.NoSpecialConstraint; } } /// /// Gets/sets the bit /// public bool HasReferenceTypeConstraint { get { return ((GenericParamAttributes)attributes & GenericParamAttributes.ReferenceTypeConstraint) != 0; } set { ModifyAttributes(value, GenericParamAttributes.ReferenceTypeConstraint); } } /// /// Gets/sets the bit /// public bool HasNotNullableValueTypeConstraint { get { return ((GenericParamAttributes)attributes & GenericParamAttributes.NotNullableValueTypeConstraint) != 0; } set { ModifyAttributes(value, GenericParamAttributes.NotNullableValueTypeConstraint); } } /// /// Gets/sets the bit /// public bool HasDefaultConstructorConstraint { get { return ((GenericParamAttributes)attributes & GenericParamAttributes.DefaultConstructorConstraint) != 0; } set { ModifyAttributes(value, GenericParamAttributes.DefaultConstructorConstraint); } } /// void IListListener.OnLazyAdd(int index, ref GenericParamConstraint value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref GenericParamConstraint value) { #if DEBUG if (value.Owner != this) throw new InvalidOperationException("Added generic param constraint's Owner != this"); #endif } /// void IListListener.OnAdd(int index, GenericParamConstraint value) { if (value.Owner != null) throw new InvalidOperationException("Generic param constraint is already owned by another generic param. Set Owner to null first."); value.Owner = this; } /// void IListListener.OnRemove(int index, GenericParamConstraint value) { value.Owner = null; } /// void IListListener.OnResize(int index) { } /// void IListListener.OnClear() { foreach (var gpc in GenericParamConstraints.GetEnumerable_NoLock()) gpc.Owner = null; } /// public override string ToString() { var o = owner; if (o is TypeDef) return string.Format("!{0}", number); if (o is MethodDef) return string.Format("!!{0}", number); return string.Format("??{0}", number); } } /// /// A GenericParam row created by the user and not present in the original .NET file /// public class GenericParamUser : GenericParam { /// /// Default constructor /// public GenericParamUser() { } /// /// Constructor /// /// The generic param number public GenericParamUser(ushort number) : this(number, 0) { } /// /// Constructor /// /// The generic param number /// Flags public GenericParamUser(ushort number, GenericParamAttributes flags) : this(number, flags, UTF8String.Empty) { } /// /// Constructor /// /// The generic param number /// Flags /// Name public GenericParamUser(ushort number, GenericParamAttributes flags, UTF8String name) { this.genericParamConstraints = new LazyList(this); this.number = number; this.attributes = (int)flags; this.name = name; } } /// /// Created from a row in the GenericParam table /// sealed class GenericParamMD : GenericParam, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.GenericParam, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), GetGenericParamContext(owner), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// protected override void InitializeGenericParamConstraints() { var list = readerModule.MetaData.GetGenericParamConstraintRidList(origRid); var tmp = new LazyList((int)list.Length, this, list, (list2, index) => readerModule.ResolveGenericParamConstraint(((RidList)list2)[index], GetGenericParamContext(owner))); Interlocked.CompareExchange(ref genericParamConstraints, tmp, null); } static GenericParamContext GetGenericParamContext(ITypeOrMethodDef tmOwner) { var md = tmOwner as MethodDef; if (md != null) return GenericParamContext.Create(md); return new GenericParamContext(tmOwner as TypeDef); } /// /// Constructor /// /// The module which contains this GenericParam row /// Row ID /// If is null /// If is invalid public GenericParamMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.GenericParamTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("GenericParam rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; uint name; uint kind = readerModule.TablesStream.ReadGenericParamRow(origRid, out this.number, out this.attributes, out name); this.name = readerModule.StringsStream.ReadNoNull(name); this.owner = readerModule.GetOwner(this); if (kind != 0) this.kind = readerModule.ResolveTypeDefOrRef(kind, GetGenericParamContext(owner)); } internal GenericParamMD InitializeAll() { MemberMDInitializer.Initialize(Owner); MemberMDInitializer.Initialize(Number); MemberMDInitializer.Initialize(Flags); MemberMDInitializer.Initialize(Name); MemberMDInitializer.Initialize(Kind); MemberMDInitializer.Initialize(CustomAttributes); MemberMDInitializer.Initialize(GenericParamConstraints); return this; } /// internal override void OnLazyAdd2(int index, ref GenericParamConstraint value) { if (value.Owner != this) { // More than one owner... This module has invalid metadata. value = readerModule.ForceUpdateRowId(readerModule.ReadGenericParamConstraint(value.Rid, GetGenericParamContext(owner)).InitializeAll()); value.Owner = this; } } } } dnlib-2.1_VS2010/src/DotNet/GenericParamAttributes.cs000066400000000000000000000015231325033663500223050ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// Generic parameter flags. See CorHdr.h/CorGenericParamAttr /// [Flags] public enum GenericParamAttributes : ushort { /// VarianceMask = 0x0003, /// NonVariant = 0x0000, /// Covariant = 0x0001, /// Contravariant = 0x0002, /// SpecialConstraintMask = 0x001C, /// NoSpecialConstraint = 0x0000, /// type argument must be a reference type ReferenceTypeConstraint = 0x0004, /// type argument must be a value type but not Nullable NotNullableValueTypeConstraint = 0x0008, /// type argument must have a public default constructor DefaultConstructorConstraint = 0x0010, } } dnlib-2.1_VS2010/src/DotNet/GenericParamConstraint.cs000066400000000000000000000134771325033663500223160ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the GenericParamConstraint table /// public abstract class GenericParamConstraint : IHasCustomAttribute, IHasCustomDebugInformation, IContainsGenericParameter { /// /// The row id in its table /// protected uint rid; /// public MDToken MDToken { get { return new MDToken(Table.GenericParamConstraint, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 20; } } /// /// Gets the owner generic param /// public GenericParam Owner { get { return owner; } internal set { owner = value; } } /// protected GenericParam owner; /// /// From column GenericParamConstraint.Constraint /// public ITypeDefOrRef Constraint { get { return constraint; } set { constraint = value; } } /// protected ITypeDefOrRef constraint; /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 20; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } bool IContainsGenericParameter.ContainsGenericParameter { get { return TypeHelper.ContainsGenericParameter(this); } } } /// /// A GenericParamConstraintAssembly row created by the user and not present in the original .NET file /// public class GenericParamConstraintUser : GenericParamConstraint { /// /// Default constructor /// public GenericParamConstraintUser() { } /// /// Constructor /// /// The constraint public GenericParamConstraintUser(ITypeDefOrRef constraint) { this.constraint = constraint; } } /// /// Created from a row in the GenericParamConstraint table /// sealed class GenericParamConstraintMD : GenericParamConstraint, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; readonly GenericParamContext gpContext; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.GenericParamConstraint, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), gpContext, list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this GenericParamConstraint row /// Row ID /// Generic parameter context /// If is null /// If is invalid public GenericParamConstraintMD(ModuleDefMD readerModule, uint rid, GenericParamContext gpContext) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.GenericParamConstraintTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("GenericParamConstraint rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; this.gpContext = gpContext; uint constraint = readerModule.TablesStream.ReadGenericParamConstraintRow2(origRid); this.constraint = readerModule.ResolveTypeDefOrRef(constraint, gpContext); this.owner = readerModule.GetOwner(this); } internal GenericParamConstraintMD InitializeAll() { MemberMDInitializer.Initialize(Owner); MemberMDInitializer.Initialize(Constraint); MemberMDInitializer.Initialize(CustomAttributes); return this; } } } dnlib-2.1_VS2010/src/DotNet/GenericParamContext.cs000066400000000000000000000046201325033663500216040ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Generic parameter context /// public struct GenericParamContext { /// /// Type context /// public readonly TypeDef Type; /// /// Method context /// public readonly MethodDef Method; /// /// true if and are both null /// public bool IsEmpty { get { return Type == null && Method == null; } } /// /// Creates a new instance and initializes the /// field to 's /// and the field to . /// /// Method /// A new instance public static GenericParamContext Create(MethodDef method) { if (method == null) return new GenericParamContext(); return new GenericParamContext(method.DeclaringType, method); } /// /// Creates a new instance and initializes the /// field to and the field /// to null /// /// Type /// A new instance public static GenericParamContext Create(TypeDef type) { return new GenericParamContext(type); } /// /// Constructor /// /// Type context public GenericParamContext(TypeDef type) { this.Type = type; this.Method = null; } /// /// Constructor. The field is set to null and NOT to /// 's . Use /// if you want that behavior. /// /// Method context public GenericParamContext(MethodDef method) { this.Type = null; this.Method = method; } /// /// Constructor /// /// Type context /// Method context public GenericParamContext(TypeDef type, MethodDef method) { this.Type = type; this.Method = method; } } } dnlib-2.1_VS2010/src/DotNet/IAssemblyResolver.cs000066400000000000000000000152031325033663500213130ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Reflection; namespace dnlib.DotNet { /// /// Resolves assemblies /// public interface IAssemblyResolver { /// /// Finds and returns an /// /// The assembly to find /// The module that needs to resolve an assembly or null /// An instance owned by the assembly resolver or /// null if the assembly couldn't be found. AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule); /// /// 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. bool AddToCache(AssemblyDef asm); /// /// 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 bool Remove(AssemblyDef asm); /// /// 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. /// void Clear(); } public static partial class Extensions { /// /// Add a module's assembly to the assembly cache /// /// this /// 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 static bool AddToCache(this IAssemblyResolver self, ModuleDef module) { return module != null && self.AddToCache(module.Assembly); } /// /// Removes a module's assembly from the cache /// /// this /// 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 static bool Remove(this IAssemblyResolver self, ModuleDef module) { return module != null && self.Remove(module.Assembly); } /// /// Finds and returns an /// /// this /// The assembly to find /// The module that needs to resolve an assembly or null /// An instance owned by the assembly resolver or /// null if the assembly couldn't be found. public static AssemblyDef Resolve(this IAssemblyResolver self, AssemblyName assembly, ModuleDef sourceModule) { if (assembly == null) return null; return self.Resolve(new AssemblyNameInfo(assembly), sourceModule); } /// /// Finds and returns an /// /// this /// The assembly to find /// The module that needs to resolve an assembly or null /// An instance owned by the assembly resolver or /// null if the assembly couldn't be found. public static AssemblyDef Resolve(this IAssemblyResolver self, string asmFullName, ModuleDef sourceModule) { if (asmFullName == null) return null; return self.Resolve(new AssemblyNameInfo(asmFullName), sourceModule); } /// /// Finds and returns an /// /// this /// The assembly to find /// The module that needs to resolve an assembly or null /// An instance owned by the assembly resolver /// If the assembly couldn't be found. public static AssemblyDef ResolveThrow(this IAssemblyResolver self, IAssembly assembly, ModuleDef sourceModule) { if (assembly == null) return null; var asm = self.Resolve(assembly, sourceModule); if (asm != null) return asm; throw new AssemblyResolveException(string.Format("Could not resolve assembly: {0}", assembly)); } /// /// Finds and returns an /// /// this /// The assembly to find /// The module that needs to resolve an assembly or null /// An instance owned by the assembly resolver /// If the assembly couldn't be found. public static AssemblyDef ResolveThrow(this IAssemblyResolver self, AssemblyName assembly, ModuleDef sourceModule) { if (assembly == null) return null; var asm = self.Resolve(new AssemblyNameInfo(assembly), sourceModule); if (asm != null) return asm; throw new AssemblyResolveException(string.Format("Could not resolve assembly: {0}", assembly)); } /// /// Finds and returns an /// /// this /// The assembly to find /// The module that needs to resolve an assembly or null /// An instance owned by the assembly resolver /// If the assembly couldn't be found. public static AssemblyDef ResolveThrow(this IAssemblyResolver self, string asmFullName, ModuleDef sourceModule) { if (asmFullName == null) return null; var asm = self.Resolve(new AssemblyNameInfo(asmFullName), sourceModule); if (asm != null) return asm; throw new AssemblyResolveException(string.Format("Could not resolve assembly: {0}", asmFullName)); } } } dnlib-2.1_VS2010/src/DotNet/ICodedToken.cs000066400000000000000000000764301325033663500200420ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.DotNet.Pdb; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// The table row can be referenced by a MD token /// public interface IMDTokenProvider { /// /// Returns the metadata token /// MDToken MDToken { get; } /// /// Gets/sets the row ID /// uint Rid { get; set; } } /// /// All *MD classes implement this interface. /// public interface IMDTokenProviderMD : IMDTokenProvider { /// /// Gets the original row ID /// uint OrigRid { get; } } /// /// An assembly. Implemented by , and /// . /// public interface IAssembly : IFullName { /// /// The assembly version /// Version Version { get; set; } /// /// Assembly flags /// AssemblyAttributes Attributes { get; set; } /// /// Public key or public key token /// PublicKeyBase PublicKeyOrToken { get; } /// /// Locale, aka culture /// UTF8String Culture { get; set; } /// /// Gets the full name of the assembly but use a public key token /// string FullNameToken { get; } /// /// Gets/sets the bit /// bool HasPublicKey { get; set; } /// /// Gets/sets the processor architecture /// AssemblyAttributes ProcessorArchitecture { get; set; } /// /// Gets/sets the processor architecture /// AssemblyAttributes ProcessorArchitectureFull { get; set; } /// /// true if unspecified processor architecture /// bool IsProcessorArchitectureNone { get; } /// /// true if neutral (PE32) architecture /// bool IsProcessorArchitectureMSIL { get; } /// /// true if x86 (PE32) architecture /// bool IsProcessorArchitectureX86 { get; } /// /// true if IA-64 (PE32+) architecture /// bool IsProcessorArchitectureIA64 { get; } /// /// true if x64 (PE32+) architecture /// bool IsProcessorArchitectureX64 { get; } /// /// true if ARM (PE32) architecture /// bool IsProcessorArchitectureARM { get; } /// /// true if eg. reference assembly (not runnable) /// bool IsProcessorArchitectureNoPlatform { get; } /// /// Gets/sets the bit /// bool IsProcessorArchitectureSpecified { get; set; } /// /// Gets/sets the bit /// bool EnableJITcompileTracking { get; set; } /// /// Gets/sets the bit /// bool DisableJITcompileOptimizer { get; set; } /// /// Gets/sets the bit /// bool IsRetargetable { get; set; } /// /// Gets/sets the content type /// AssemblyAttributes ContentType { get; set; } /// /// true if content type is Default /// bool IsContentTypeDefault { get; } /// /// true if content type is WindowsRuntime /// bool IsContentTypeWindowsRuntime { get; } } public static partial class Extensions { /// /// Checks whether appears to be the core library (eg. /// mscorlib, System.Runtime or corefx). /// /// If is a reference to a private corlib (eg. System.Private.CoreLib), /// this method returns false unless is an /// whose manifest (first) module defines System.Object. This check is performed in /// the constructor and the result can be found in . /// /// Note that this method also returns true if it appears to be a 'public' corlib, /// eg. mscorlib, etc, even if it internally possibly references a private corlib. /// /// The assembly public static bool IsCorLib(this IAssembly asm) { var asmDef = asm as AssemblyDef; if (asmDef != null) { var manifestModule = asmDef.ManifestModule; if (manifestModule != null) { var isCorModule = manifestModule.IsCoreLibraryModule; if (isCorModule != null) return isCorModule.Value; } } string asmName; return asm != null && UTF8String.IsNullOrEmpty(asm.Culture) && ((asmName = UTF8String.ToSystemStringOrEmpty(asm.Name)).Equals("mscorlib", StringComparison.OrdinalIgnoreCase) || asmName.Equals("System.Runtime", StringComparison.OrdinalIgnoreCase) || // This name could change but since CoreCLR is used a lot, it's worth supporting asmName.Equals("System.Private.CoreLib", StringComparison.OrdinalIgnoreCase) || asmName.Equals("netstandard", StringComparison.OrdinalIgnoreCase) || asmName.Equals("corefx", StringComparison.OrdinalIgnoreCase)); } /// /// Converts to a instance /// /// The assembly /// A new instance public static AssemblyRef ToAssemblyRef(this IAssembly asm) { if (asm == null) return null; // Always create a new one, even if it happens to be an AssemblyRef return new AssemblyRefUser(asm.Name, asm.Version, asm.PublicKeyOrToken, asm.Culture) { Attributes = asm.Attributes }; } /// /// Converts to a /// /// The type /// true if we should try to figure out whether /// is a /// A instance or null if /// is invalid public static TypeSig ToTypeSig(this ITypeDefOrRef type, bool checkValueType = true) { if (type == null) return null; var module = type.Module; if (module != null) { var corLibType = module.CorLibTypes.GetCorLibTypeSig(type); if (corLibType != null) return corLibType; } var td = type as TypeDef; if (td != null) return CreateClassOrValueType(type, checkValueType ? td.IsValueType : false); var tr = type as TypeRef; if (tr != null) { if (checkValueType) td = tr.Resolve(); return CreateClassOrValueType(type, td == null ? false : td.IsValueType); } var ts = type as TypeSpec; if (ts != null) return ts.TypeSig; return null; } static TypeSig CreateClassOrValueType(ITypeDefOrRef type, bool isValueType) { if (isValueType) return new ValueTypeSig(type); return new ClassSig(type); } /// /// Returns a /// /// The type /// A or null if it's not a /// public static TypeDefOrRefSig TryGetTypeDefOrRefSig(this ITypeDefOrRef type) { var ts = type as TypeSpec; return ts == null ? null : ts.TypeSig.RemovePinnedAndModifiers() as TypeDefOrRefSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static ClassOrValueTypeSig TryGetClassOrValueTypeSig(this ITypeDefOrRef type) { var ts = type as TypeSpec; return ts == null ? null : ts.TypeSig.RemovePinnedAndModifiers() as ClassOrValueTypeSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static ValueTypeSig TryGetValueTypeSig(this ITypeDefOrRef type) { var ts = type as TypeSpec; return ts == null ? null : ts.TypeSig.RemovePinnedAndModifiers() as ValueTypeSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static ClassSig TryGetClassSig(this ITypeDefOrRef type) { var ts = type as TypeSpec; return ts == null ? null : ts.TypeSig.RemovePinnedAndModifiers() as ClassSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static GenericSig TryGetGenericSig(this ITypeDefOrRef type) { var ts = type as TypeSpec; return ts == null ? null : ts.TypeSig.RemovePinnedAndModifiers() as GenericSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static GenericVar TryGetGenericVar(this ITypeDefOrRef type) { var ts = type as TypeSpec; return ts == null ? null : ts.TypeSig.RemovePinnedAndModifiers() as GenericVar; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static GenericMVar TryGetGenericMVar(this ITypeDefOrRef type) { var ts = type as TypeSpec; return ts == null ? null : ts.TypeSig.RemovePinnedAndModifiers() as GenericMVar; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static GenericInstSig TryGetGenericInstSig(this ITypeDefOrRef type) { var ts = type as TypeSpec; return ts == null ? null : ts.TypeSig.RemovePinnedAndModifiers() as GenericInstSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static PtrSig TryGetPtrSig(this ITypeDefOrRef type) { var ts = type as TypeSpec; return ts == null ? null : ts.TypeSig.RemovePinnedAndModifiers() as PtrSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static ByRefSig TryGetByRefSig(this ITypeDefOrRef type) { var ts = type as TypeSpec; return ts == null ? null : ts.TypeSig.RemovePinnedAndModifiers() as ByRefSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static ArraySig TryGetArraySig(this ITypeDefOrRef type) { var ts = type as TypeSpec; return ts == null ? null : ts.TypeSig.RemovePinnedAndModifiers() as ArraySig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static SZArraySig TryGetSZArraySig(this ITypeDefOrRef type) { var ts = type as TypeSpec; return ts == null ? null : ts.TypeSig.RemovePinnedAndModifiers() as SZArraySig; } /// /// Returns the base type of . Throws if we can't resolve /// a . /// /// The type /// The base type or null if there's no base type public static ITypeDefOrRef GetBaseTypeThrow(this ITypeDefOrRef tdr) { return tdr.GetBaseType(true); } /// /// Returns the base type of /// /// The type /// true if we should throw if we can't /// resolve a . false if we should ignore the error and /// just return null. /// The base type or null if there's no base type, or if /// is true and we couldn't resolve /// a public static ITypeDefOrRef GetBaseType(this ITypeDefOrRef tdr, bool throwOnResolveFailure = false) { var td = tdr as TypeDef; if (td != null) return td.BaseType; var tr = tdr as TypeRef; if (tr != null) { td = throwOnResolveFailure ? tr.ResolveThrow() : tr.Resolve(); return td == null ? null : td.BaseType; } var ts = tdr as TypeSpec; if (ts == null) return null; var git = ts.TypeSig.ToGenericInstSig(); if (git != null) { var genType = git.GenericType; tdr = genType == null ? null : genType.TypeDefOrRef; } else { var sig = ts.TypeSig.ToTypeDefOrRefSig(); tdr = sig == null ? null : sig.TypeDefOrRef; } td = tdr as TypeDef; if (td != null) return td.BaseType; tr = tdr as TypeRef; if (tr != null) { td = throwOnResolveFailure ? tr.ResolveThrow() : tr.Resolve(); return td == null ? null : td.BaseType; } return null; } /// /// Gets the scope type, resolves it, and returns the /// /// Type /// A or null if input was null or if we /// couldn't resolve the reference. public static TypeDef ResolveTypeDef(this ITypeDefOrRef tdr) { var td = tdr as TypeDef; if (td != null) return td; var tr = tdr as TypeRef; if (tr != null) return tr.Resolve(); if (tdr == null) return null; tdr = tdr.ScopeType; td = tdr as TypeDef; if (td != null) return td; tr = tdr as TypeRef; if (tr != null) return tr.Resolve(); return null; } /// /// Gets the scope type, resolves it, and returns the /// /// Type /// A instance. /// If the type couldn't be resolved public static TypeDef ResolveTypeDefThrow(this ITypeDefOrRef tdr) { var td = tdr as TypeDef; if (td != null) return td; var tr = tdr as TypeRef; if (tr != null) return tr.ResolveThrow(); if (tdr == null) throw new TypeResolveException("Can't resolve a null pointer"); tdr = tdr.ScopeType; td = tdr as TypeDef; if (td != null) return td; tr = tdr as TypeRef; if (tr != null) return tr.ResolveThrow(); throw new TypeResolveException(string.Format("Could not resolve type: {0} ({1})", tdr, tdr == null ? null : tdr.DefinitionAssembly)); } /// /// Resolves an to a . Returns null if it /// was not possible to resolve it. See also /// /// Field to resolve /// The or null if is /// null or if it wasn't possible to resolve it (the field doesn't exist or its /// assembly couldn't be loaded) public static FieldDef ResolveFieldDef(this IField field) { var fd = field as FieldDef; if (fd != null) return fd; var mr = field as MemberRef; if (mr != null) return mr.ResolveField(); return null; } /// /// Resolves an to a and throws an exception if /// it was not possible to resolve it. See also /// /// Field to resolve /// The public static FieldDef ResolveFieldDefThrow(this IField field) { var fd = field as FieldDef; if (fd != null) return fd; var mr = field as MemberRef; if (mr != null) return mr.ResolveFieldThrow(); throw new MemberRefResolveException(string.Format("Could not resolve field: {0}", field)); } /// /// Resolves an to a . Returns null if it /// was not possible to resolve it. See also . If /// is a , then the /// property is resolved and returned. /// /// Method to resolve /// The or null if is /// null or if it wasn't possible to resolve it (the method doesn't exist or its /// assembly couldn't be loaded) public static MethodDef ResolveMethodDef(this IMethod method) { var md = method as MethodDef; if (md != null) return md; var mr = method as MemberRef; if (mr != null) return mr.ResolveMethod(); var ms = method as MethodSpec; if (ms != null) { md = ms.Method as MethodDef; if (md != null) return md; mr = ms.Method as MemberRef; if (mr != null) return mr.ResolveMethod(); } return null; } /// /// Resolves an to a and throws an exception /// if it was not possible to resolve it. See also . If /// is a , then the /// property is resolved and returned. /// /// Method to resolve /// The public static MethodDef ResolveMethodDefThrow(this IMethod method) { var md = method as MethodDef; if (md != null) return md; var mr = method as MemberRef; if (mr != null) return mr.ResolveMethodThrow(); var ms = method as MethodSpec; if (ms != null) { md = ms.Method as MethodDef; if (md != null) return md; mr = ms.Method as MemberRef; if (mr != null) return mr.ResolveMethodThrow(); } throw new MemberRefResolveException(string.Format("Could not resolve method: {0}", method)); } /// /// Returns the definition assembly of a /// /// Member reference /// static internal IAssembly GetDefinitionAssembly(this MemberRef mr) { if (mr == null) return null; var parent = mr.Class; var tdr = parent as ITypeDefOrRef; if (tdr != null) return tdr.DefinitionAssembly; if (parent is ModuleRef) { var mod = mr.Module; return mod == null ? null : mod.Assembly; } var md = parent as MethodDef; if (md != null) { var declType = md.DeclaringType; return declType == null ? null : declType.DefinitionAssembly; } return null; } } /// /// Implemented by and , which are the only /// valid managed entry point tokens. /// public interface IManagedEntryPoint : ICodedToken { } /// /// Interface to access a module def/ref /// public interface IModule : IScope, IFullName { } /// /// Type of scope /// public enum ScopeType { /// /// It's an instance /// AssemblyRef, /// /// It's a instance /// ModuleRef, /// /// It's a instance /// ModuleDef, } /// /// Implemented by modules and assemblies /// public interface IScope { /// /// Gets the scope type /// ScopeType ScopeType { get; } /// /// Gets the scope name /// string ScopeName { get; } } /// /// Interface to get the full name of a type, field, or method /// public interface IFullName { /// /// Gets the full name /// string FullName { get; } /// /// Simple name of implementer /// UTF8String Name { get; set; } } /// /// Implemented by all member refs and types /// public interface IOwnerModule { /// /// Gets the owner module /// ModuleDef Module { get; } } /// /// Methods to check whether the implementer is a type or a method. /// public interface IIsTypeOrMethod { /// /// true if it's a type /// bool IsType { get; } /// /// true if it's a method /// bool IsMethod { get; } } /// /// Implemented by types, fields, methods, properties, events /// public interface IMemberRef : ICodedToken, IFullName, IOwnerModule, IIsTypeOrMethod { /// /// Gets the declaring type /// ITypeDefOrRef DeclaringType { get; } /// /// true if it's a or a that's /// referencing a field. /// bool IsField { get; } /// /// true if it's a /// bool IsTypeSpec { get; } /// /// true if it's a /// bool IsTypeRef { get; } /// /// true if it's a /// bool IsTypeDef { get; } /// /// true if it's a /// bool IsMethodSpec { get; } /// /// true if it's a /// bool IsMethodDef { get; } /// /// true if it's a /// bool IsMemberRef { get; } /// /// true if it's a /// bool IsFieldDef { get; } /// /// true if it's a /// bool IsPropertyDef { get; } /// /// true if it's a /// bool IsEventDef { get; } /// /// true if it's a /// bool IsGenericParam { get; } } /// /// All member definitions implement this interface: , /// , , , /// , and . /// public interface IMemberDef : IDnlibDef, IMemberRef { /// /// Gets the declaring type /// new TypeDef DeclaringType { get; } } /// /// Implemented by the following classes: , /// , , , /// , , , /// and /// public interface IDnlibDef : ICodedToken, IFullName, IHasCustomAttribute { } /// /// Implemented by types and methods /// public interface IGenericParameterProvider : ICodedToken, IIsTypeOrMethod { /// /// Gets the number of generic parameters / arguments /// int NumberOfGenericParameters { get; } } /// /// Implemented by fields ( and ) /// public interface IField : ICodedToken, ITokenOperand, IFullName, IMemberRef { /// /// Gets/sets the field signature /// FieldSig FieldSig { get; set; } } /// /// Implemented by methods (, and ) /// public interface IMethod : ICodedToken, ITokenOperand, IFullName, IGenericParameterProvider, IMemberRef { /// /// Method signature /// MethodSig MethodSig { get; set; } } /// /// Implemented by tables that can be a token in the ldtoken instruction /// public interface ITokenOperand : ICodedToken { } /// /// The table row can be referenced by a coded token /// public interface ICodedToken : IMDTokenProvider { } /// /// TypeDefOrRef coded token interface /// public interface ITypeDefOrRef : ICodedToken, IHasCustomAttribute, IMemberRefParent, IType, ITokenOperand, IMemberRef { /// /// The coded token tag /// int TypeDefOrRefTag { get; } } /// /// HasConstant coded token interface /// public interface IHasConstant : ICodedToken, IHasCustomAttribute, IFullName { /// /// The coded token tag /// int HasConstantTag { get; } /// /// Gets/sets the constant value /// Constant Constant { get; set; } } /// /// HasCustomAttribute coded token interface /// public interface IHasCustomAttribute : ICodedToken { /// /// The coded token tag /// int HasCustomAttributeTag { get; } /// /// Gets all custom attributes /// CustomAttributeCollection CustomAttributes { get; } /// /// true if is not empty /// bool HasCustomAttributes { get; } } /// /// HasFieldMarshal coded token interface /// public interface IHasFieldMarshal : ICodedToken, IHasCustomAttribute, IHasConstant, IFullName { /// /// The coded token tag /// int HasFieldMarshalTag { get; } /// /// Gets/sets the marshal type /// MarshalType MarshalType { get; set; } /// /// true if is not null /// bool HasMarshalType { get; } } /// /// HasDeclSecurity coded token interface /// public interface IHasDeclSecurity : ICodedToken, IHasCustomAttribute, IFullName { /// /// The coded token tag /// int HasDeclSecurityTag { get; } /// /// Gets the permission sets /// ThreadSafe.IList DeclSecurities { get; } /// /// true if is not empty /// bool HasDeclSecurities { get; } } /// /// MemberRefParent coded token interface /// public interface IMemberRefParent : ICodedToken, IHasCustomAttribute, IFullName { /// /// The coded token tag /// int MemberRefParentTag { get; } } /// /// HasSemantic coded token interface /// public interface IHasSemantic : ICodedToken, IHasCustomAttribute, IFullName, IMemberRef { /// /// The coded token tag /// int HasSemanticTag { get; } } /// /// MethodDefOrRef coded token interface /// public interface IMethodDefOrRef : ICodedToken, IHasCustomAttribute, ICustomAttributeType, IMethod { /// /// The coded token tag /// int MethodDefOrRefTag { get; } } /// /// MemberForwarded coded token interface /// public interface IMemberForwarded : ICodedToken, IHasCustomAttribute, IFullName, IMemberRef { /// /// The coded token tag /// int MemberForwardedTag { get; } /// /// Gets/sets the impl map /// ImplMap ImplMap { get; set; } /// /// true if is not null /// bool HasImplMap { get; } } /// /// Implementation coded token interface /// public interface IImplementation : ICodedToken, IHasCustomAttribute, IFullName { /// /// The coded token tag /// int ImplementationTag { get; } } /// /// CustomAttributeType coded token interface /// public interface ICustomAttributeType : ICodedToken, IHasCustomAttribute, IMethod { /// /// The coded token tag /// int CustomAttributeTypeTag { get; } } /// /// ResolutionScope coded token interface /// public interface IResolutionScope : ICodedToken, IHasCustomAttribute, IFullName { /// /// The coded token tag /// int ResolutionScopeTag { get; } } /// /// TypeOrMethodDef coded token interface /// public interface ITypeOrMethodDef : ICodedToken, IHasCustomAttribute, IHasDeclSecurity, IMemberRefParent, IFullName, IMemberRef, IGenericParameterProvider { /// /// The coded token tag /// int TypeOrMethodDefTag { get; } /// /// Gets the generic parameters /// ThreadSafe.IList GenericParameters { get; } /// /// true if is not empty /// bool HasGenericParameters { get; } } /// /// HasCustomDebugInformation interface /// public interface IHasCustomDebugInformation { /// /// The custom debug information tag /// int HasCustomDebugInformationTag { get; } /// /// Gets the custom debug infos /// ThreadSafe.IList CustomDebugInfos { get; } /// /// true if is not empty /// bool HasCustomDebugInfos { get; } } public static partial class Extensions { /// /// Converts a to a /// /// The sig public static ITypeDefOrRef ToTypeDefOrRef(this TypeSig sig) { if (sig == null) return null; var tdrSig = sig as TypeDefOrRefSig; if (tdrSig != null) return tdrSig.TypeDefOrRef; var module = sig.Module; if (module == null) return new TypeSpecUser(sig); return module.UpdateRowId(new TypeSpecUser(sig)); } /// /// Returns true if it's an integer or a floating point type /// /// Type /// internal static bool IsPrimitive(this IType tdr) { if (tdr == null) return false; if (!tdr.DefinitionAssembly.IsCorLib()) return false; switch (tdr.FullName) { case "System.Boolean": case "System.Char": case "System.SByte": case "System.Byte": case "System.Int16": case "System.UInt16": case "System.Int32": case "System.UInt32": case "System.Int64": case "System.UInt64": case "System.Single": case "System.Double": case "System.IntPtr": case "System.UIntPtr": return true; default: return false; } } } } dnlib-2.1_VS2010/src/DotNet/ICorLibTypes.cs000066400000000000000000000127041325033663500202140ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Access to .NET core library's simple types /// public interface ICorLibTypes { /// /// Gets a System.Void /// CorLibTypeSig Void { get; } /// /// Gets a System.Boolean /// CorLibTypeSig Boolean { get; } /// /// Gets a System.Char /// CorLibTypeSig Char { get; } /// /// Gets a System.SByte /// CorLibTypeSig SByte { get; } /// /// Gets a System.Byte /// CorLibTypeSig Byte { get; } /// /// Gets a System.Int16 /// CorLibTypeSig Int16 { get; } /// /// Gets a System.UInt16 /// CorLibTypeSig UInt16 { get; } /// /// Gets a System.Int32 /// CorLibTypeSig Int32 { get; } /// /// Gets a System.UInt32 /// CorLibTypeSig UInt32 { get; } /// /// Gets a System.Int64 /// CorLibTypeSig Int64 { get; } /// /// Gets a System.UInt64 /// CorLibTypeSig UInt64 { get; } /// /// Gets a System.Single /// CorLibTypeSig Single { get; } /// /// Gets a System.Double /// CorLibTypeSig Double { get; } /// /// Gets a System.String /// CorLibTypeSig String { get; } /// /// Gets a System.TypedReference /// CorLibTypeSig TypedReference { get; } /// /// Gets a System.IntPtr /// CorLibTypeSig IntPtr { get; } /// /// Gets a System.UIntPtr /// CorLibTypeSig UIntPtr { get; } /// /// Gets a System.Object /// CorLibTypeSig Object { get; } /// /// Gets the assembly reference to the core library /// AssemblyRef AssemblyRef { get; } /// /// Gets a that references a type in the core library assembly /// /// Namespace of type (eg. "System") /// Name of type /// A instance. This instance may be a cached instance. TypeRef GetTypeRef(string @namespace, string name); } public static partial class Extensions { /// /// Gets a if matches a primitive type. /// /// this /// The type /// A or null if it didn't match any primitive type public static CorLibTypeSig GetCorLibTypeSig(this ICorLibTypes self, ITypeDefOrRef type) { CorLibTypeSig corLibType; TypeDef td; if ((td = type as TypeDef) != null && td.DeclaringType == null && (corLibType = self.GetCorLibTypeSig(td.Namespace, td.Name, td.DefinitionAssembly)) != null) { return corLibType; } TypeRef tr; if ((tr = type as TypeRef) != null && !(tr.ResolutionScope is TypeRef) && (corLibType = self.GetCorLibTypeSig(tr.Namespace, tr.Name, tr.DefinitionAssembly)) != null) { return corLibType; } return null; } /// /// Gets a if and /// matches a primitive type. /// /// this /// Namespace /// Name /// Definition assembly /// A or null if it didn't match any primitive type public static CorLibTypeSig GetCorLibTypeSig(this ICorLibTypes self, UTF8String @namespace, UTF8String name, IAssembly defAsm) { return self.GetCorLibTypeSig(UTF8String.ToSystemStringOrEmpty(@namespace), UTF8String.ToSystemStringOrEmpty(name), defAsm); } /// /// Gets a if and /// matches a primitive type. /// /// this /// Namespace /// Name /// Definition assembly /// A or null if it didn't match any primitive type public static CorLibTypeSig GetCorLibTypeSig(this ICorLibTypes self, string @namespace, string name, IAssembly defAsm) { if (@namespace != "System") return null; if (defAsm == null || !defAsm.IsCorLib()) return null; switch (name) { case "Void": return self.Void; case "Boolean": return self.Boolean; case "Char": return self.Char; case "SByte": return self.SByte; case "Byte": return self.Byte; case "Int16": return self.Int16; case "UInt16": return self.UInt16; case "Int32": return self.Int32; case "UInt32": return self.UInt32; case "Int64": return self.Int64; case "UInt64": return self.UInt64; case "Single": return self.Single; case "Double": return self.Double; case "String": return self.String; case "TypedReference": return self.TypedReference; case "IntPtr": return self.IntPtr; case "UIntPtr": return self.UIntPtr; case "Object": return self.Object; } return null; } } } dnlib-2.1_VS2010/src/DotNet/ICustomAttribute.cs000066400000000000000000000023161325033663500211510ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// Custom attribute interface. Implemented by and /// /// public interface ICustomAttribute { /// /// Gets the attribute type /// ITypeDefOrRef AttributeType { get; } /// /// Gets the full name of the attribute type /// string TypeFullName { get; } /// /// Gets all named arguments (field and property values) /// ThreadSafe.IList NamedArguments { get; } /// /// true if is not empty /// bool HasNamedArguments { get; } /// /// Gets all s that are field arguments /// IEnumerable Fields { get; } /// /// Gets all s that are property arguments /// IEnumerable Properties { get; } } } dnlib-2.1_VS2010/src/DotNet/IDecrypters.cs000066400000000000000000000025311325033663500201360ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using dnlib.PE; using dnlib.DotNet.Emit; namespace dnlib.DotNet { /// /// Interface to decrypt methods /// public interface IMethodDecrypter { /// /// Gets the method's body /// /// Method rid /// The found in the method's Method row /// The method's parameters /// Generic parameter context /// Updated with the method's if this /// method returns true /// true if the method body was decrypted, false if the method isn't /// encrypted and the default body reader code should be used. bool GetMethodBody(uint rid, RVA rva, IList parameters, GenericParamContext gpContext, out MethodBody methodBody); } /// /// Interface to decrypt strings /// public interface IStringDecrypter { /// /// Reads a string /// /// String token /// A string or null if we should read it from the #US heap string ReadUserString(uint token); } } dnlib-2.1_VS2010/src/DotNet/ILogger.cs000066400000000000000000000417501325033663500172370ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Reflection; using dnlib.DotNet.Writer; namespace dnlib.DotNet { /// /// events /// public enum LoggerEvent { /// /// An error was detected. An exception should normally be thrown but the error /// can be ignored. /// Error, /// /// Just a warning and can be ignored. /// Warning, /// /// A normal message /// Info, /// /// A verbose message /// Verbose, /// /// A very verbose message /// VeryVerbose, } /// /// Simple logger /// public interface ILogger { /// /// Log something /// /// Caller or null /// Logger event /// Format /// Arguments void Log(object sender, LoggerEvent loggerEvent, string format, params object[] args); /// /// true if this event is ignored. If the event is ignored, the caller can /// choose not to call . This is useful if it can take time to /// prepare the message. /// /// The logger event bool IgnoresEvent(LoggerEvent loggerEvent); } public static partial class Extensions { /// /// Log an error message /// /// this /// Sender or null /// Message public static void Error(this ILogger logger, object sender, string message) { logger.Log(sender, LoggerEvent.Error, "{0}", message); } /// /// Log an error message /// /// this /// Sender or null /// Message /// Message arg #1 public static void Error(this ILogger logger, object sender, string message, object arg1) { logger.Log(sender, LoggerEvent.Error, message, arg1); } /// /// Log an error message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 public static void Error(this ILogger logger, object sender, string message, object arg1, object arg2) { logger.Log(sender, LoggerEvent.Error, message, arg1, arg2); } /// /// Log an error message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 public static void Error(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) { logger.Log(sender, LoggerEvent.Error, message, arg1, arg2, arg3); } /// /// Log an error message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 /// Message arg #4 public static void Error(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) { logger.Log(sender, LoggerEvent.Error, message, arg1, arg2, arg3, arg4); } /// /// Log an error message /// /// this /// Sender or null /// Message /// Message arguments public static void Error(this ILogger logger, object sender, string message, params object[] args) { logger.Log(sender, LoggerEvent.Error, message, args); } /// /// Log a warning message /// /// this /// Sender or null /// Message public static void Warning(this ILogger logger, object sender, string message) { logger.Log(sender, LoggerEvent.Warning, "{0}", message); } /// /// Log a warning message /// /// this /// Sender or null /// Message /// Message arg #1 public static void Warning(this ILogger logger, object sender, string message, object arg1) { logger.Log(sender, LoggerEvent.Warning, message, arg1); } /// /// Log a warning message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 public static void Warning(this ILogger logger, object sender, string message, object arg1, object arg2) { logger.Log(sender, LoggerEvent.Warning, message, arg1, arg2); } /// /// Log a warning message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 public static void Warning(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) { logger.Log(sender, LoggerEvent.Warning, message, arg1, arg2, arg3); } /// /// Log a warning message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 /// Message arg #4 public static void Warning(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) { logger.Log(sender, LoggerEvent.Warning, message, arg1, arg2, arg3, arg4); } /// /// Log a warning message /// /// this /// Sender or null /// Message /// Message arguments public static void Warning(this ILogger logger, object sender, string message, params object[] args) { logger.Log(sender, LoggerEvent.Warning, message, args); } /// /// Log an info message /// /// this /// Sender or null /// Message public static void Info(this ILogger logger, object sender, string message) { logger.Log(sender, LoggerEvent.Info, "{0}", message); } /// /// Log an info message /// /// this /// Sender or null /// Message /// Message arg #1 public static void Info(this ILogger logger, object sender, string message, object arg1) { logger.Log(sender, LoggerEvent.Info, message, arg1); } /// /// Log an info message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 public static void Info(this ILogger logger, object sender, string message, object arg1, object arg2) { logger.Log(sender, LoggerEvent.Info, message, arg1, arg2); } /// /// Log an info message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 public static void Info(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) { logger.Log(sender, LoggerEvent.Info, message, arg1, arg2, arg3); } /// /// Log an info message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 /// Message arg #4 public static void Info(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) { logger.Log(sender, LoggerEvent.Info, message, arg1, arg2, arg3, arg4); } /// /// Log an info message /// /// this /// Sender or null /// Message /// Message arguments public static void Info(this ILogger logger, object sender, string message, params object[] args) { logger.Log(sender, LoggerEvent.Info, message, args); } /// /// Log a verbose message /// /// this /// Sender or null /// Message public static void Verbose(this ILogger logger, object sender, string message) { logger.Log(sender, LoggerEvent.Verbose, "{0}", message); } /// /// Log a verbose message /// /// this /// Sender or null /// Message /// Message arg #1 public static void Verbose(this ILogger logger, object sender, string message, object arg1) { logger.Log(sender, LoggerEvent.Verbose, message, arg1); } /// /// Log a verbose message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 public static void Verbose(this ILogger logger, object sender, string message, object arg1, object arg2) { logger.Log(sender, LoggerEvent.Verbose, message, arg1, arg2); } /// /// Log a verbose message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 public static void Verbose(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) { logger.Log(sender, LoggerEvent.Verbose, message, arg1, arg2, arg3); } /// /// Log a verbose message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 /// Message arg #4 public static void Verbose(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) { logger.Log(sender, LoggerEvent.Verbose, message, arg1, arg2, arg3, arg4); } /// /// Log a verbose message /// /// this /// Sender or null /// Message /// Message arguments public static void Verbose(this ILogger logger, object sender, string message, params object[] args) { logger.Log(sender, LoggerEvent.Verbose, message, args); } /// /// Log a very verbose message /// /// this /// Sender or null /// Message public static void VeryVerbose(this ILogger logger, object sender, string message) { logger.Log(sender, LoggerEvent.VeryVerbose, "{0}", message); } /// /// Log a very verbose message /// /// this /// Sender or null /// Message /// Message arg #1 public static void VeryVerbose(this ILogger logger, object sender, string message, object arg1) { logger.Log(sender, LoggerEvent.VeryVerbose, message, arg1); } /// /// Log a very verbose message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 public static void VeryVerbose(this ILogger logger, object sender, string message, object arg1, object arg2) { logger.Log(sender, LoggerEvent.VeryVerbose, message, arg1, arg2); } /// /// Log a very verbose message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 public static void VeryVerbose(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) { logger.Log(sender, LoggerEvent.VeryVerbose, message, arg1, arg2, arg3); } /// /// Log a very verbose message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 /// Message arg #4 public static void VeryVerbose(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) { logger.Log(sender, LoggerEvent.VeryVerbose, message, arg1, arg2, arg3, arg4); } /// /// Log a very verbose message /// /// this /// Sender or null /// Message /// Message arguments public static void VeryVerbose(this ILogger logger, object sender, string message, params object[] args) { logger.Log(sender, LoggerEvent.VeryVerbose, message, args); } } /// /// Dummy logger which ignores all messages, but can optionally throw on errors. /// public sealed class DummyLogger : ILogger { ConstructorInfo ctor; /// /// It ignores everything and doesn't throw anything. /// public static readonly DummyLogger NoThrowInstance = new DummyLogger(); /// /// Throws a on errors, but ignores anything else. /// public static readonly DummyLogger ThrowModuleWriterExceptionOnErrorInstance = new DummyLogger(typeof(ModuleWriterException)); DummyLogger() { } /// /// Constructor /// /// If non-null, this exception type is thrown on /// errors. It must have a public constructor that takes a as the only /// argument. public DummyLogger(Type exceptionToThrow) { if (exceptionToThrow != null) { if (!exceptionToThrow.IsSubclassOf(typeof(Exception))) throw new ArgumentException(string.Format("Not a System.Exception sub class: {0}", exceptionToThrow.GetType())); ctor = exceptionToThrow.GetConstructor(new Type[] { typeof(string) }); if (ctor == null) throw new ArgumentException(string.Format("Exception type {0} doesn't have a public constructor that takes a string as the only argument", exceptionToThrow.GetType())); } } /// public void Log(object sender, LoggerEvent loggerEvent, string format, params object[] args) { if (loggerEvent == LoggerEvent.Error && ctor != null) throw (Exception)ctor.Invoke(new object[] { string.Format(format, args) }); } /// public bool IgnoresEvent(LoggerEvent loggerEvent) { if (ctor == null) return true; return loggerEvent != LoggerEvent.Error; } } } dnlib-2.1_VS2010/src/DotNet/IResolver.cs000066400000000000000000000127141325033663500176170ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Resolves types, methods, fields /// public interface IResolver : ITypeResolver, IMemberRefResolver { } /// /// Resolves types /// public interface ITypeResolver { /// /// Resolves a type /// /// The type /// The module that needs to resolve the type or null /// A instance or null if it couldn't be resolved TypeDef Resolve(TypeRef typeRef, ModuleDef sourceModule); } /// /// Resolves fields and methods /// public interface IMemberRefResolver { /// /// Resolves a method or a field /// /// A method/field reference /// A or a instance or null /// if it couldn't be resolved. IMemberForwarded Resolve(MemberRef memberRef); } public static partial class Extensions { /// /// Resolves a type /// /// this /// The type /// A instance or null if it couldn't be resolved public static TypeDef Resolve(this ITypeResolver self, TypeRef typeRef) { return self.Resolve(typeRef, null); } /// /// Resolves a type /// /// this /// The type /// A instance /// If the type couldn't be resolved public static TypeDef ResolveThrow(this ITypeResolver self, TypeRef typeRef) { return self.ResolveThrow(typeRef, null); } /// /// Resolves a type /// /// this /// The type /// The module that needs to resolve the type or null /// A instance /// If the type couldn't be resolved public static TypeDef ResolveThrow(this ITypeResolver self, TypeRef typeRef, ModuleDef sourceModule) { var type = self.Resolve(typeRef, sourceModule); if (type != null) return type; throw new TypeResolveException(string.Format("Could not resolve type: {0} ({1})", typeRef, typeRef == null ? null : typeRef.DefinitionAssembly)); } /// /// Resolves a method or a field /// /// this /// A method/field reference /// A or a instance /// If the method/field couldn't be resolved public static IMemberForwarded ResolveThrow(this IMemberRefResolver self, MemberRef memberRef) { var memberDef = self.Resolve(memberRef); if (memberDef != null) return memberDef; throw new MemberRefResolveException(string.Format("Could not resolve method/field: {0} ({1})", memberRef, memberRef == null ? null : memberRef.GetDefinitionAssembly())); } /// /// Resolves a field /// /// this /// A field reference /// A instance or null if it couldn't be resolved. public static FieldDef ResolveField(this IMemberRefResolver self, MemberRef memberRef) { return self.Resolve(memberRef) as FieldDef; } /// /// Resolves a field /// /// this /// A field reference /// A instance or null if it couldn't be resolved. /// If the field couldn't be resolved public static FieldDef ResolveFieldThrow(this IMemberRefResolver self, MemberRef memberRef) { var field = self.Resolve(memberRef) as FieldDef; if (field != null) return field; throw new MemberRefResolveException(string.Format("Could not resolve field: {0} ({1})", memberRef, memberRef == null ? null : memberRef.GetDefinitionAssembly())); } /// /// Resolves a method /// /// this /// A method reference /// A instance or null if it couldn't be resolved. public static MethodDef ResolveMethod(this IMemberRefResolver self, MemberRef memberRef) { return self.Resolve(memberRef) as MethodDef; } /// /// Resolves a method /// /// this /// A method reference /// A instance or null if it couldn't be resolved. /// If the method couldn't be resolved public static MethodDef ResolveMethodThrow(this IMemberRefResolver self, MemberRef memberRef) { var method = self.Resolve(memberRef) as MethodDef; if (method != null) return method; throw new MemberRefResolveException(string.Format("Could not resolve method: {0} ({1})", memberRef, memberRef == null ? null : memberRef.GetDefinitionAssembly())); } } } dnlib-2.1_VS2010/src/DotNet/ITokenResolver.cs000066400000000000000000000017241325033663500206170ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Resolves tokens /// public interface ITokenResolver { /// /// Resolves a token /// /// The metadata token /// Generic parameter context /// A or null if is invalid IMDTokenProvider ResolveToken(uint token, GenericParamContext gpContext); } public static partial class Extensions { /// /// Resolves a token /// /// This /// The metadata token /// A or null if is invalid public static IMDTokenProvider ResolveToken(this ITokenResolver self, uint token) { return self.ResolveToken(token, new GenericParamContext()); } } } dnlib-2.1_VS2010/src/DotNet/IType.cs000066400000000000000000000064771325033663500167500ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Interface to get the full name of a type /// public interface IType : IFullName, IOwnerModule, ICodedToken, IGenericParameterProvider, IContainsGenericParameter { /// /// true if it's a value type /// bool IsValueType { get; } /// /// Returns the name of this type /// string TypeName { get; } /// /// Returns the reflection name of this type /// string ReflectionName { get; } /// /// Returns the namespace of this type /// string Namespace { get; } /// /// Returns the reflection namespace of this type /// string ReflectionNamespace { get; } /// /// Returns the reflection name of this type. See also . /// string ReflectionFullName { get; } /// /// Returns the reflection name of this type, and includes the assembly name where the /// type is located. It can be passed to to /// load the type. /// string AssemblyQualifiedName { get; } /// /// Gets the assembly where this type is defined /// IAssembly DefinitionAssembly { get; } /// /// Gets the scope, which is different from since it /// can differentiate between modules within the same assembly. /// IScope Scope { get; } /// /// Gets the type whose scope is returned by and whose assembly /// is returned by . This is always a /// , or null. It can also be a /// nested . /// For example, if this type is a System.String&, then this value is a System.String. /// If it's a generic instance type (eg. List<int>), then the generic type is /// returned (eg. List<T>). In other words, the first or /// that is found (without searching generic arguments) is returned. /// ITypeDefOrRef ScopeType { get; } /// /// true if it's an integer or a floating point type /// bool IsPrimitive { get; } } /// /// Implemented by types and calling convention signatures. /// public interface IContainsGenericParameter { /// /// true if this contains a or a . /// bool ContainsGenericParameter { get; } } public static partial class Extensions { /// /// Returns , but if it's a nested , /// return the non-nested /// /// this /// The scope type public static ITypeDefOrRef GetNonNestedTypeRefScope(this IType type) { if (type == null) return null; var scopeType = type.ScopeType; var tr = scopeType as TypeRef; if (tr == null) return scopeType; for (int i = 0; i < 100; i++) { var dt = tr.ResolutionScope as TypeRef; if (dt == null) return tr; tr = dt; } return tr; } } } dnlib-2.1_VS2010/src/DotNet/ITypeDefFinder.cs000066400000000000000000000154301325033663500205040ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Finds s /// public interface ITypeDefFinder { /// /// Finds a /// /// Full name of the type (no assembly information) /// true if it's a reflection name, and nested /// type names are separated by a + character. If false, nested type names /// are separated by a / character. /// An existing or null if it wasn't found. TypeDef Find(string fullName, bool isReflectionName); /// /// Finds a . 's scope (i.e., module or /// assembly) is ignored when looking up the type. /// /// The type ref /// An existing or null if it wasn't found. TypeDef Find(TypeRef typeRef); } public static partial class Extensions { /// /// Finds a . Its scope (i.e., module or assembly) is ignored when /// looking up the type. /// /// this /// The type ref /// An existing or null if it wasn't found. /// If type couldn't be found public static TypeDef FindThrow(this ITypeDefFinder self, TypeRef typeRef) { var type = self.Find(typeRef); if (type != null) return type; throw new TypeResolveException(string.Format("Could not find type: {0}", typeRef)); } /// /// Finds a /// /// this /// Full name of the type (no assembly information) /// true if it's a reflection name, and nested /// type names are separated by a + character. If false, nested type names /// are separated by a / character. /// An existing /// If type couldn't be found public static TypeDef FindThrow(this ITypeDefFinder self, string fullName, bool isReflectionName) { var type = self.Find(fullName, isReflectionName); if (type != null) return type; throw new TypeResolveException(string.Format("Could not find type: {0}", fullName)); } /// /// Finds a /// /// this /// Full name of the type (no assembly information). Nested types are separated by / /// An existing or null if it wasn't found. public static TypeDef FindNormal(this ITypeDefFinder self, string fullName) { return self.Find(fullName, false); } /// /// Finds a /// /// this /// Full name of the type (no assembly information). Nested types are separated by / /// An existing /// If type couldn't be found public static TypeDef FindNormalThrow(this ITypeDefFinder self, string fullName) { var type = self.Find(fullName, false); if (type != null) return type; throw new TypeResolveException(string.Format("Could not find type: {0}", fullName)); } /// /// Finds a /// /// this /// Full name of the type (no assembly information). Nested types are separated by + /// An existing or null if it wasn't found. public static TypeDef FindReflection(this ITypeDefFinder self, string fullName) { return self.Find(fullName, true); } /// /// Finds a /// /// this /// Full name of the type (no assembly information). Nested types are separated by + /// An existing /// If type couldn't be found public static TypeDef FindReflectionThrow(this ITypeDefFinder self, string fullName) { var type = self.Find(fullName, true); if (type != null) return type; throw new TypeResolveException(string.Format("Could not find type: {0}", fullName)); } /// /// Checks whether a exists. 's scope (i.e., /// module or assembly) is ignored when looking up the type. /// /// this /// The type ref /// true if the exists, false otherwise public static bool TypeExists(this ITypeDefFinder self, TypeRef typeRef) { return self.Find(typeRef) != null; } /// /// Checks whether a exists /// /// this /// Full name of the type (no assembly information) /// true if it's a reflection name, and nested /// type names are separated by a + character. If false, nested type names /// are separated by a / character. /// true if the exists, false otherwise public static bool TypeExists(this ITypeDefFinder self, string fullName, bool isReflectionName) { return self.Find(fullName, isReflectionName) != null; } /// /// Checks whether a exists /// /// this /// Full name of the type (no assembly information). Nested types are separated by / /// true if the exists, false otherwise public static bool TypeExistsNormal(this ITypeDefFinder self, string fullName) { return self.Find(fullName, false) != null; } /// /// Checks whether a exists /// /// this /// Full name of the type (no assembly information). Nested types are separated by + /// true if the exists, false otherwise public static bool TypeExistsReflection(this ITypeDefFinder self, string fullName) { return self.Find(fullName, true) != null; } } } dnlib-2.1_VS2010/src/DotNet/IVariable.cs000066400000000000000000000007041325033663500175370ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Interface to access a local or a parameter /// public interface IVariable { /// /// Gets the variable type /// TypeSig Type { get; } /// /// Gets the 0-based position /// int Index { get; } /// /// Gets/sets the variable name /// string Name { get; set; } } } dnlib-2.1_VS2010/src/DotNet/ImplMap.cs000066400000000000000000000256531325033663500172520ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.Threading; using dnlib.DotNet.MD; namespace dnlib.DotNet { /// /// A high-level representation of a row in the ImplMap table /// [DebuggerDisplay("{Module} {Name}")] public abstract class ImplMap : IMDTokenProvider { /// /// The row id in its table /// protected uint rid; /// public MDToken MDToken { get { return new MDToken(Table.ImplMap, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// /// From column ImplMap.MappingFlags /// public PInvokeAttributes Attributes { get { return (PInvokeAttributes)attributes; } set { attributes = (int)value; } } /// Attributes protected int attributes; /// /// From column ImplMap.ImportName /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// From column ImplMap.ImportScope /// public ModuleRef Module { get { return module; } set { module = value; } } /// protected ModuleRef module; /// /// Modify property: = /// ( & ) | . /// /// Value to AND /// Value to OR void ModifyAttributes(PInvokeAttributes andMask, PInvokeAttributes 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 attributes = (attributes & (int)andMask) | (int)orMask; #endif } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyAttributes(bool set, PInvokeAttributes 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 IsNoMangle { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.NoMangle) != 0; } set { ModifyAttributes(value, PInvokeAttributes.NoMangle); } } /// /// Gets/sets the char set /// public PInvokeAttributes CharSet { get { return (PInvokeAttributes)attributes & PInvokeAttributes.CharSetMask; } set { ModifyAttributes(~PInvokeAttributes.CharSetMask, value & PInvokeAttributes.CharSetMask); } } /// /// true if is set /// public bool IsCharSetNotSpec { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.CharSetMask) == PInvokeAttributes.CharSetNotSpec; } } /// /// true if is set /// public bool IsCharSetAnsi { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.CharSetMask) == PInvokeAttributes.CharSetAnsi; } } /// /// true if is set /// public bool IsCharSetUnicode { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.CharSetMask) == PInvokeAttributes.CharSetUnicode; } } /// /// true if is set /// public bool IsCharSetAuto { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.CharSetMask) == PInvokeAttributes.CharSetAuto; } } /// /// Gets/sets best fit /// public PInvokeAttributes BestFit { get { return (PInvokeAttributes)attributes & PInvokeAttributes.BestFitMask; } set { ModifyAttributes(~PInvokeAttributes.BestFitMask, value & PInvokeAttributes.BestFitMask); } } /// /// true if is set /// public bool IsBestFitUseAssem { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.BestFitMask) == PInvokeAttributes.BestFitUseAssem; } } /// /// true if is set /// public bool IsBestFitEnabled { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.BestFitMask) == PInvokeAttributes.BestFitEnabled; } } /// /// true if is set /// public bool IsBestFitDisabled { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.BestFitMask) == PInvokeAttributes.BestFitDisabled; } } /// /// Gets/sets throw on unmappable char /// public PInvokeAttributes ThrowOnUnmappableChar { get { return (PInvokeAttributes)attributes & PInvokeAttributes.ThrowOnUnmappableCharMask; } set { ModifyAttributes(~PInvokeAttributes.ThrowOnUnmappableCharMask, value & PInvokeAttributes.ThrowOnUnmappableCharMask); } } /// /// true if is set /// public bool IsThrowOnUnmappableCharUseAssem { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.ThrowOnUnmappableCharMask) == PInvokeAttributes.ThrowOnUnmappableCharUseAssem; } } /// /// true if is set /// public bool IsThrowOnUnmappableCharEnabled { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.ThrowOnUnmappableCharMask) == PInvokeAttributes.ThrowOnUnmappableCharEnabled; } } /// /// true if is set /// public bool IsThrowOnUnmappableCharDisabled { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.ThrowOnUnmappableCharMask) == PInvokeAttributes.ThrowOnUnmappableCharDisabled; } } /// /// Gets/sets the bit /// public bool SupportsLastError { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.SupportsLastError) != 0; } set { ModifyAttributes(value, PInvokeAttributes.SupportsLastError); } } /// /// Gets/sets calling convention /// public PInvokeAttributes CallConv { get { return (PInvokeAttributes)attributes & PInvokeAttributes.CallConvMask; } set { ModifyAttributes(~PInvokeAttributes.CallConvMask, value & PInvokeAttributes.CallConvMask); } } /// /// true if is set /// public bool IsCallConvWinapi { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.CallConvMask) == PInvokeAttributes.CallConvWinapi; } } /// /// true if is set /// public bool IsCallConvCdecl { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.CallConvMask) == PInvokeAttributes.CallConvCdecl; } } /// /// true if is set /// public bool IsCallConvStdcall { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.CallConvMask) == PInvokeAttributes.CallConvStdcall; } } /// /// true if is set /// public bool IsCallConvThiscall { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.CallConvMask) == PInvokeAttributes.CallConvThiscall; } } /// /// true if is set /// public bool IsCallConvFastcall { get { return ((PInvokeAttributes)attributes & PInvokeAttributes.CallConvMask) == PInvokeAttributes.CallConvFastcall; } } /// /// Checks whether this is a certain P/Invoke method /// /// Name of the DLL /// Name of the function within the DLL /// true if it's the specified P/Invoke method, else false public bool IsPinvokeMethod(string dllName, string funcName) { if (name != funcName) return false; var mod = module; if (mod == null) return false; return GetDllName(dllName).Equals(GetDllName(mod.Name), StringComparison.OrdinalIgnoreCase); } static string GetDllName(string dllName) { if (dllName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) return dllName.Substring(0, dllName.Length - 4); return dllName; } } /// /// An ImplMap row created by the user and not present in the original .NET file /// public class ImplMapUser : ImplMap { /// /// Default constructor /// public ImplMapUser() { } /// /// Constructor /// /// Scope /// Name /// Flags public ImplMapUser(ModuleRef scope, UTF8String name, PInvokeAttributes flags) { this.module = scope; this.name = name; this.attributes = (int)flags; } } /// /// Created from a row in the ImplMap table /// sealed class ImplMapMD : ImplMap, IMDTokenProviderMD { readonly uint origRid; /// public uint OrigRid { get { return origRid; } } /// /// Constructor /// /// The module which contains this ImplMap row /// Row ID /// If is null /// If is invalid public ImplMapMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.ImplMapTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("ImplMap rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; uint name; uint scope = readerModule.TablesStream.ReadImplMapRow(origRid, out this.attributes, out name); this.name = readerModule.StringsStream.ReadNoNull(name); this.module = readerModule.ResolveModuleRef(scope); } } } dnlib-2.1_VS2010/src/DotNet/Importer.cs000066400000000000000000001121051325033663500175010ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Reflection; using dnlib.Threading; namespace dnlib.DotNet { /// /// options /// [Flags] public enum ImporterOptions { /// /// Use s whenever possible if the is located /// in this module. /// TryToUseTypeDefs = 1, /// /// Use s whenever possible if the is located /// in this module. /// TryToUseMethodDefs = 2, /// /// Use s whenever possible if the is located /// in this module. /// TryToUseFieldDefs = 4, /// /// Use s, s and s /// whenever possible if the definition is located in this module. /// /// /// /// TryToUseDefs = TryToUseTypeDefs | TryToUseMethodDefs | TryToUseFieldDefs, /// /// Don't set this flag. For internal use only. /// FixSignature = int.MinValue, } /// /// Imports s, s, s /// and s as references /// public struct Importer { readonly ModuleDef module; readonly GenericParamContext gpContext; RecursionCounter recursionCounter; ImporterOptions options; bool TryToUseTypeDefs { get { return (options & ImporterOptions.TryToUseTypeDefs) != 0; } } bool TryToUseMethodDefs { get { return (options & ImporterOptions.TryToUseMethodDefs) != 0; } } bool TryToUseFieldDefs { get { return (options & ImporterOptions.TryToUseFieldDefs) != 0; } } bool FixSignature { get { return (options & ImporterOptions.FixSignature) != 0; } set { if (value) options |= ImporterOptions.FixSignature; else options &= ~ImporterOptions.FixSignature; } } /// /// Constructor /// /// The module that will own all references public Importer(ModuleDef module) : this(module, 0, new GenericParamContext()) { } /// /// Constructor /// /// The module that will own all references /// Generic parameter context public Importer(ModuleDef module, GenericParamContext gpContext) : this(module, 0, gpContext) { } /// /// Constructor /// /// The module that will own all references /// Importer options public Importer(ModuleDef module, ImporterOptions options) : this(module, options, new GenericParamContext()) { } /// /// Constructor /// /// The module that will own all references /// Importer options /// Generic parameter context public Importer(ModuleDef module, ImporterOptions options, GenericParamContext gpContext) { this.module = module; this.recursionCounter = new RecursionCounter(); this.options = options; this.gpContext = gpContext; } /// /// Imports a as a /// /// The type /// The imported type or null if is invalid public ITypeDefOrRef Import(Type type) { return module.UpdateRowId(ImportAsTypeSig(type).ToTypeDefOrRef()); } /// /// Imports a as a /// /// The type /// A list of all required modifiers or null /// A list of all optional modifiers or null /// The imported type or null if is invalid public ITypeDefOrRef Import(Type type, IList requiredModifiers, IList optionalModifiers) { return module.UpdateRowId(ImportAsTypeSig(type, requiredModifiers, optionalModifiers).ToTypeDefOrRef()); } /// /// Imports a as a /// /// The type /// The imported type or null if is invalid public TypeSig ImportAsTypeSig(Type type) { return ImportAsTypeSig(type, false); } TypeSig ImportAsTypeSig(Type type, bool treatAsGenericInst) { if (type == null) return null; switch (treatAsGenericInst ? ElementType.GenericInst : type.GetElementType2()) { case ElementType.Void: return module.CorLibTypes.Void; case ElementType.Boolean: return module.CorLibTypes.Boolean; case ElementType.Char: return module.CorLibTypes.Char; case ElementType.I1: return module.CorLibTypes.SByte; case ElementType.U1: return module.CorLibTypes.Byte; case ElementType.I2: return module.CorLibTypes.Int16; case ElementType.U2: return module.CorLibTypes.UInt16; case ElementType.I4: return module.CorLibTypes.Int32; case ElementType.U4: return module.CorLibTypes.UInt32; case ElementType.I8: return module.CorLibTypes.Int64; case ElementType.U8: return module.CorLibTypes.UInt64; case ElementType.R4: return module.CorLibTypes.Single; case ElementType.R8: return module.CorLibTypes.Double; case ElementType.String: return module.CorLibTypes.String; case ElementType.TypedByRef:return module.CorLibTypes.TypedReference; case ElementType.U: return module.CorLibTypes.UIntPtr; case ElementType.Object: return module.CorLibTypes.Object; case ElementType.Ptr: return new PtrSig(ImportAsTypeSig(type.GetElementType(), treatAsGenericInst)); case ElementType.ByRef: return new ByRefSig(ImportAsTypeSig(type.GetElementType(), treatAsGenericInst)); case ElementType.SZArray: return new SZArraySig(ImportAsTypeSig(type.GetElementType(), treatAsGenericInst)); case ElementType.ValueType: return new ValueTypeSig(CreateTypeRef(type)); case ElementType.Class: return new ClassSig(CreateTypeRef(type)); case ElementType.Var: return new GenericVar((uint)type.GenericParameterPosition, gpContext.Type); case ElementType.MVar: return new GenericMVar((uint)type.GenericParameterPosition, gpContext.Method); case ElementType.I: FixSignature = true; // FnPtr is mapped to System.IntPtr return module.CorLibTypes.IntPtr; case ElementType.Array: FixSignature = true; // We don't know sizes and lower bounds return new ArraySig(ImportAsTypeSig(type.GetElementType(), treatAsGenericInst), (uint)type.GetArrayRank()); case ElementType.GenericInst: var typeGenArgs = type.GetGenericArguments(); var git = new GenericInstSig(ImportAsTypeSig(type.GetGenericTypeDefinition()) as ClassOrValueTypeSig, (uint)typeGenArgs.Length); foreach (var ga in typeGenArgs) git.GenericArguments.Add(ImportAsTypeSig(ga)); return git; case ElementType.Sentinel: case ElementType.Pinned: case ElementType.FnPtr: // mapped to System.IntPtr case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.ValueArray: case ElementType.R: case ElementType.Internal: case ElementType.Module: case ElementType.End: default: return null; } } ITypeDefOrRef TryResolve(TypeRef tr) { if (!TryToUseTypeDefs || tr == null) return tr; if (!IsThisModule(tr)) return tr; var td = tr.Resolve(); if (td == null || td.Module != module) return tr; return td; } IMethodDefOrRef TryResolveMethod(IMethodDefOrRef mdr) { if (!TryToUseMethodDefs || mdr == null) return mdr; var mr = mdr as MemberRef; if (mr == null) return mdr; if (!mr.IsMethodRef) return mr; var declType = GetDeclaringType(mr); if (declType == null) return mr; if (declType.Module != module) return mr; return (IMethodDefOrRef)declType.ResolveMethod(mr) ?? mr; } IField TryResolveField(MemberRef mr) { if (!TryToUseFieldDefs || mr == null) return mr; if (!mr.IsFieldRef) return mr; var declType = GetDeclaringType(mr); if (declType == null) return mr; if (declType.Module != module) return mr; return (IField)declType.ResolveField(mr) ?? mr; } TypeDef GetDeclaringType(MemberRef mr) { if (mr == null) return null; var td = mr.Class as TypeDef; if (td != null) return td; td = TryResolve(mr.Class as TypeRef) as TypeDef; if (td != null) return td; var modRef = mr.Class as ModuleRef; if (IsThisModule(modRef)) return module.GlobalType; return null; } bool IsThisModule(TypeRef tr) { if (tr == null) return false; var scopeType = tr.ScopeType.GetNonNestedTypeRefScope() as TypeRef; if (scopeType == null) return false; if (module == scopeType.ResolutionScope) return true; var modRef = scopeType.ResolutionScope as ModuleRef; if (modRef != null) return IsThisModule(modRef); var asmRef = scopeType.ResolutionScope as AssemblyRef; return Equals(module.Assembly, asmRef); } bool IsThisModule(ModuleRef modRef) { return modRef != null && module.Name == modRef.Name && Equals(module.Assembly, modRef.DefinitionAssembly); } static bool Equals(IAssembly a, IAssembly b) { if (a == b) return true; if (a == null || b == null) return false; return Utils.Equals(a.Version, b.Version) && PublicKeyBase.TokenEquals(a.PublicKeyOrToken, b.PublicKeyOrToken) && UTF8String.Equals(a.Name, b.Name) && UTF8String.CaseInsensitiveEquals(a.Culture, b.Culture); } ITypeDefOrRef CreateTypeRef(Type type) { return TryResolve(CreateTypeRef2(type)); } TypeRef CreateTypeRef2(Type type) { if (!type.IsNested) return module.UpdateRowId(new TypeRefUser(module, type.Namespace ?? string.Empty, type.Name ?? string.Empty, CreateScopeReference(type))); return module.UpdateRowId(new TypeRefUser(module, string.Empty, type.Name ?? string.Empty, CreateTypeRef2(type.DeclaringType))); } IResolutionScope CreateScopeReference(Type type) { if (type == null) return null; var asmName = type.Assembly.GetName(); var modAsm = module.Assembly; if (modAsm != null) { if (UTF8String.ToSystemStringOrEmpty(modAsm.Name).Equals(asmName.Name, StringComparison.OrdinalIgnoreCase)) { if (UTF8String.ToSystemStringOrEmpty(module.Name).Equals(type.Module.ScopeName, StringComparison.OrdinalIgnoreCase)) return module; return module.UpdateRowId(new ModuleRefUser(module, type.Module.ScopeName)); } } var pkt = asmName.GetPublicKeyToken(); if (pkt == null || pkt.Length == 0) pkt = null; return module.UpdateRowId(new AssemblyRefUser(asmName.Name, asmName.Version, PublicKeyBase.CreatePublicKeyToken(pkt), asmName.CultureInfo.Name)); } /// /// Imports a as a /// /// The type /// A list of all required modifiers or null /// A list of all optional modifiers or null /// The imported type or null if is invalid public TypeSig ImportAsTypeSig(Type type, IList requiredModifiers, IList optionalModifiers) { return ImportAsTypeSig(type, requiredModifiers, optionalModifiers, false); } TypeSig ImportAsTypeSig(Type type, IList requiredModifiers, IList optionalModifiers, bool treatAsGenericInst) { if (type == null) return null; if (IsEmpty(requiredModifiers) && IsEmpty(optionalModifiers)) return ImportAsTypeSig(type, treatAsGenericInst); FixSignature = true; // Order of modifiers is unknown var ts = ImportAsTypeSig(type, treatAsGenericInst); // We don't know the original order of the modifiers. // Assume all required modifiers are closer to the real type. // Assume all modifiers should be applied in the same order as in the lists. if (requiredModifiers != null) { foreach (var modifier in requiredModifiers.GetSafeEnumerable()) ts = new CModReqdSig(Import(modifier), ts); } if (optionalModifiers != null) { foreach (var modifier in optionalModifiers.GetSafeEnumerable()) ts = new CModOptSig(Import(modifier), ts); } return ts; } static bool IsEmpty(IList list) { return list == null || list.Count == 0; } /// /// Imports a as a . This will be either /// a or a . /// /// The method /// The imported method or null if is invalid /// or if we failed to import the method public IMethod Import(MethodBase methodBase) { return Import(methodBase, false); } /// /// Imports a as a . This will be either /// a or a . /// /// The method /// Always verify method signature to make sure the /// returned reference matches the metadata in the source assembly /// The imported method or null if is invalid /// or if we failed to import the method public IMethod Import(MethodBase methodBase, bool forceFixSignature) { FixSignature = false; return ImportInternal(methodBase, forceFixSignature); } IMethod ImportInternal(MethodBase methodBase) { return ImportInternal(methodBase, false); } IMethod ImportInternal(MethodBase methodBase, bool forceFixSignature) { if (methodBase == null) return null; if (forceFixSignature) { //TODO: } bool isMethodSpec = methodBase.IsGenericButNotGenericMethodDefinition(); if (isMethodSpec) { IMethodDefOrRef method; var origMethod = methodBase.Module.ResolveMethod(methodBase.MetadataToken); if (methodBase.DeclaringType.GetElementType2() == ElementType.GenericInst) method = module.UpdateRowId(new MemberRefUser(module, methodBase.Name, CreateMethodSig(origMethod), Import(methodBase.DeclaringType))); else method = ImportInternal(origMethod) as IMethodDefOrRef; method = TryResolveMethod(method); var gim = CreateGenericInstMethodSig(methodBase); var methodSpec = module.UpdateRowId(new MethodSpecUser(method, gim)); if (FixSignature && !forceFixSignature) { //TODO: } return methodSpec; } else { IMemberRefParent parent; if (methodBase.DeclaringType == null) { // It's the global type. We can reference it with a ModuleRef token. parent = GetModuleParent(methodBase.Module); } else parent = Import(methodBase.DeclaringType); if (parent == null) return null; MethodBase origMethod; try { // Get the original method def in case the declaring type is a generic // type instance and the method uses at least one generic type parameter. origMethod = methodBase.Module.ResolveMethod(methodBase.MetadataToken); } catch (ArgumentException) { // Here if eg. the method was created by the runtime (eg. a multi-dimensional // array getter/setter method). The method token is in that case 0x06000000, // which is invalid. origMethod = methodBase; } var methodSig = CreateMethodSig(origMethod); IMethodDefOrRef methodRef = module.UpdateRowId(new MemberRefUser(module, methodBase.Name, methodSig, parent)); methodRef = TryResolveMethod(methodRef); if (FixSignature && !forceFixSignature) { //TODO: } return methodRef; } } MethodSig CreateMethodSig(MethodBase mb) { var sig = new MethodSig(GetCallingConvention(mb)); var mi = mb as MethodInfo; if (mi != null) sig.RetType = ImportAsTypeSig(mi.ReturnParameter, mb.DeclaringType); else sig.RetType = module.CorLibTypes.Void; foreach (var p in mb.GetParameters()) sig.Params.Add(ImportAsTypeSig(p, mb.DeclaringType)); if (mb.IsGenericMethodDefinition) sig.GenParamCount = (uint)mb.GetGenericArguments().Length; return sig; } TypeSig ImportAsTypeSig(ParameterInfo p, Type declaringType) { return ImportAsTypeSig(p.ParameterType, p.GetRequiredCustomModifiers(), p.GetOptionalCustomModifiers(), declaringType.MustTreatTypeAsGenericInstType(p.ParameterType)); } CallingConvention GetCallingConvention(MethodBase mb) { CallingConvention cc = 0; var mbcc = mb.CallingConvention; if (mb.IsGenericMethodDefinition) cc |= CallingConvention.Generic; if ((mbcc & CallingConventions.HasThis) != 0) cc |= CallingConvention.HasThis; if ((mbcc & CallingConventions.ExplicitThis) != 0) cc |= CallingConvention.ExplicitThis; switch (mbcc & CallingConventions.Any) { case CallingConventions.Standard: cc |= CallingConvention.Default; break; case CallingConventions.VarArgs: cc |= CallingConvention.VarArg; break; case CallingConventions.Any: default: FixSignature = true; cc |= CallingConvention.Default; break; } return cc; } GenericInstMethodSig CreateGenericInstMethodSig(MethodBase mb) { var genMethodArgs = mb.GetGenericArguments(); var gim = new GenericInstMethodSig(CallingConvention.GenericInst, (uint)genMethodArgs.Length); foreach (var gma in genMethodArgs) gim.GenericArguments.Add(ImportAsTypeSig(gma)); return gim; } IMemberRefParent GetModuleParent(Module module2) { // If we have no assembly, assume this is a netmodule in the same assembly as module var modAsm = module.Assembly; bool isSameAssembly = modAsm == null || UTF8String.ToSystemStringOrEmpty(modAsm.Name).Equals(module2.Assembly.GetName().Name, StringComparison.OrdinalIgnoreCase); if (!isSameAssembly) return null; return module.UpdateRowId(new ModuleRefUser(module, module.Name)); } /// /// Imports a as a /// /// The field /// The imported field or null if is invalid /// or if we failed to import the field public IField Import(FieldInfo fieldInfo) { return Import(fieldInfo, false); } /// /// Imports a as a /// /// The field /// Always verify field signature to make sure the /// returned reference matches the metadata in the source assembly /// The imported field or null if is invalid /// or if we failed to import the field public IField Import(FieldInfo fieldInfo, bool forceFixSignature) { FixSignature = false; if (fieldInfo == null) return null; if (forceFixSignature) { //TODO: } IMemberRefParent parent; if (fieldInfo.DeclaringType == null) { // It's the global type. We can reference it with a ModuleRef token. parent = GetModuleParent(fieldInfo.Module); } else parent = Import(fieldInfo.DeclaringType); if (parent == null) return null; FieldInfo origField; try { // Get the original field def in case the declaring type is a generic // type instance and the field uses a generic type parameter. origField = fieldInfo.Module.ResolveField(fieldInfo.MetadataToken); } catch (ArgumentException) { origField = fieldInfo; } MemberRef fieldRef; if (origField.FieldType.ContainsGenericParameters) { var origDeclType = origField.DeclaringType; var asm = module.Context.AssemblyResolver.Resolve(origDeclType.Module.Assembly.GetName(), module); if (asm == null || asm.FullName != origDeclType.Assembly.FullName) throw new Exception("Couldn't resolve the correct assembly"); var mod = asm.FindModule(origDeclType.Module.Name) as ModuleDefMD; if (mod == null) throw new Exception("Couldn't resolve the correct module"); var fieldDef = mod.ResolveField((uint)(origField.MetadataToken & 0x00FFFFFF)); if (fieldDef == null) throw new Exception("Couldn't resolve the correct field"); var fieldSig = new FieldSig(Import(fieldDef.FieldSig.GetFieldType())); fieldRef = module.UpdateRowId(new MemberRefUser(module, fieldInfo.Name, fieldSig, parent)); } else { var fieldSig = new FieldSig(ImportAsTypeSig(fieldInfo.FieldType, fieldInfo.GetRequiredCustomModifiers(), fieldInfo.GetOptionalCustomModifiers())); fieldRef = module.UpdateRowId(new MemberRefUser(module, fieldInfo.Name, fieldSig, parent)); } var field = TryResolveField(fieldRef); if (FixSignature && !forceFixSignature) { //TODO: } return field; } /// /// Imports a /// /// The type /// The imported type or null public IType Import(IType type) { if (type == null) return null; if (!recursionCounter.Increment()) return null; IType result; TypeDef td; TypeRef tr; TypeSpec ts; TypeSig sig; if ((td = type as TypeDef) != null) result = Import(td); else if ((tr = type as TypeRef) != null) result = Import(tr); else if ((ts = type as TypeSpec) != null) result = Import(ts); else if ((sig = type as TypeSig) != null) result = Import(sig); else result = null; recursionCounter.Decrement(); return result; } /// /// Imports a as a /// /// The type /// The imported type or null public ITypeDefOrRef Import(TypeDef type) { if (type == null) return null; if (TryToUseTypeDefs && type.Module == module) return type; return Import2(type); } TypeRef Import2(TypeDef type) { if (type == null) return null; if (!recursionCounter.Increment()) return null; TypeRef result; var declType = type.DeclaringType; if (declType != null) result = module.UpdateRowId(new TypeRefUser(module, type.Namespace, type.Name, Import2(declType))); else result = module.UpdateRowId(new TypeRefUser(module, type.Namespace, type.Name, CreateScopeReference(type.DefinitionAssembly, type.Module))); recursionCounter.Decrement(); return result; } IResolutionScope CreateScopeReference(IAssembly defAsm, ModuleDef defMod) { if (defAsm == null) return null; var modAsm = module.Assembly; if (defMod != null && defAsm != null && modAsm != null) { if (UTF8String.CaseInsensitiveEquals(modAsm.Name, defAsm.Name)) { if (UTF8String.CaseInsensitiveEquals(module.Name, defMod.Name)) return module; return module.UpdateRowId(new ModuleRefUser(module, defMod.Name)); } } var pkt = PublicKeyBase.ToPublicKeyToken(defAsm.PublicKeyOrToken); if (PublicKeyBase.IsNullOrEmpty2(pkt)) pkt = null; return module.UpdateRowId(new AssemblyRefUser(defAsm.Name, defAsm.Version, pkt, defAsm.Culture) { Attributes = defAsm.Attributes & ~AssemblyAttributes.PublicKey }); } /// /// Imports a /// /// The type /// The imported type or null public ITypeDefOrRef Import(TypeRef type) { return TryResolve(Import2(type)); } TypeRef Import2(TypeRef type) { if (type == null) return null; if (!recursionCounter.Increment()) return null; TypeRef result; var declaringType = type.DeclaringType; if (declaringType != null) result = module.UpdateRowId(new TypeRefUser(module, type.Namespace, type.Name, Import2(declaringType))); else result = module.UpdateRowId(new TypeRefUser(module, type.Namespace, type.Name, CreateScopeReference(type.DefinitionAssembly, type.Module))); recursionCounter.Decrement(); return result; } /// /// Imports a /// /// The type /// The imported type or null public TypeSpec Import(TypeSpec type) { if (type == null) return null; return module.UpdateRowId(new TypeSpecUser(Import(type.TypeSig))); } /// /// Imports a /// /// The type /// The imported type or null public TypeSig Import(TypeSig type) { if (type == null) return null; if (!recursionCounter.Increment()) return null; TypeSig result; switch (type.ElementType) { case ElementType.Void: result = module.CorLibTypes.Void; break; case ElementType.Boolean: result = module.CorLibTypes.Boolean; break; case ElementType.Char: result = module.CorLibTypes.Char; break; case ElementType.I1: result = module.CorLibTypes.SByte; break; case ElementType.U1: result = module.CorLibTypes.Byte; break; case ElementType.I2: result = module.CorLibTypes.Int16; break; case ElementType.U2: result = module.CorLibTypes.UInt16; break; case ElementType.I4: result = module.CorLibTypes.Int32; break; case ElementType.U4: result = module.CorLibTypes.UInt32; break; case ElementType.I8: result = module.CorLibTypes.Int64; break; case ElementType.U8: result = module.CorLibTypes.UInt64; break; case ElementType.R4: result = module.CorLibTypes.Single; break; case ElementType.R8: result = module.CorLibTypes.Double; break; case ElementType.String: result = module.CorLibTypes.String; break; case ElementType.TypedByRef:result = module.CorLibTypes.TypedReference; break; case ElementType.I: result = module.CorLibTypes.IntPtr; break; case ElementType.U: result = module.CorLibTypes.UIntPtr; break; case ElementType.Object: result = module.CorLibTypes.Object; break; case ElementType.Ptr: result = new PtrSig(Import(type.Next)); break; case ElementType.ByRef: result = new ByRefSig(Import(type.Next)); break; case ElementType.ValueType: result = CreateClassOrValueType((type as ClassOrValueTypeSig).TypeDefOrRef, true); break; case ElementType.Class: result = CreateClassOrValueType((type as ClassOrValueTypeSig).TypeDefOrRef, false); break; case ElementType.Var: result = new GenericVar((type as GenericVar).Number, gpContext.Type); break; case ElementType.ValueArray:result = new ValueArraySig(Import(type.Next), (type as ValueArraySig).Size); break; case ElementType.FnPtr: result = new FnPtrSig(Import((type as FnPtrSig).Signature)); break; case ElementType.SZArray: result = new SZArraySig(Import(type.Next)); break; case ElementType.MVar: result = new GenericMVar((type as GenericMVar).Number, gpContext.Method); break; case ElementType.CModReqd: result = new CModReqdSig(Import((type as ModifierSig).Modifier), Import(type.Next)); break; case ElementType.CModOpt: result = new CModOptSig(Import((type as ModifierSig).Modifier), Import(type.Next)); break; case ElementType.Module: result = new ModuleSig((type as ModuleSig).Index, Import(type.Next)); break; case ElementType.Sentinel: result = new SentinelSig(); break; case ElementType.Pinned: result = new PinnedSig(Import(type.Next)); break; case ElementType.Array: var arraySig = (ArraySig)type; var sizes = new List(arraySig.Sizes); var lbounds = new List(arraySig.LowerBounds); result = new ArraySig(Import(type.Next), arraySig.Rank, sizes, lbounds); break; case ElementType.GenericInst: var gis = (GenericInstSig)type; var genArgs = new List(gis.GenericArguments.Count); foreach (var ga in gis.GenericArguments.GetSafeEnumerable()) genArgs.Add(Import(ga)); result = new GenericInstSig(Import(gis.GenericType) as ClassOrValueTypeSig, genArgs); break; case ElementType.End: case ElementType.R: case ElementType.Internal: default: result = null; break; } recursionCounter.Decrement(); return result; } ITypeDefOrRef Import(ITypeDefOrRef type) { return (ITypeDefOrRef)Import((IType)type); } TypeSig CreateClassOrValueType(ITypeDefOrRef type, bool isValueType) { var corLibType = module.CorLibTypes.GetCorLibTypeSig(type); if (corLibType != null) return corLibType; if (isValueType) return new ValueTypeSig(Import(type)); return new ClassSig(Import(type)); } /// /// Imports a /// /// The sig /// The imported sig or null if input is invalid public CallingConventionSig Import(CallingConventionSig sig) { if (sig == null) return null; if (!recursionCounter.Increment()) return null; CallingConventionSig result; var sigType = sig.GetType(); if (sigType == typeof(MethodSig)) result = Import((MethodSig)sig); else if (sigType == typeof(FieldSig)) result = Import((FieldSig)sig); else if (sigType == typeof(GenericInstMethodSig)) result = Import((GenericInstMethodSig)sig); else if (sigType == typeof(PropertySig)) result = Import((PropertySig)sig); else if (sigType == typeof(LocalSig)) result = Import((LocalSig)sig); else result = null; // Should never be reached recursionCounter.Decrement(); return result; } /// /// Imports a /// /// The sig /// The imported sig or null if input is invalid public FieldSig Import(FieldSig sig) { if (sig == null) return null; if (!recursionCounter.Increment()) return null; var result = new FieldSig(sig.GetCallingConvention(), Import(sig.Type)); recursionCounter.Decrement(); return result; } /// /// Imports a /// /// The sig /// The imported sig or null if input is invalid public MethodSig Import(MethodSig sig) { if (sig == null) return null; if (!recursionCounter.Increment()) return null; MethodSig result = Import(new MethodSig(sig.GetCallingConvention()), sig); recursionCounter.Decrement(); return result; } T Import(T sig, T old) where T : MethodBaseSig { sig.RetType = Import(old.RetType); foreach (var p in old.Params.GetSafeEnumerable()) sig.Params.Add(Import(p)); sig.GenParamCount = old.GenParamCount; var paramsAfterSentinel = sig.ParamsAfterSentinel; if (paramsAfterSentinel != null) { foreach (var p in old.ParamsAfterSentinel.GetSafeEnumerable()) paramsAfterSentinel.Add(Import(p)); } return sig; } /// /// Imports a /// /// The sig /// The imported sig or null if input is invalid public PropertySig Import(PropertySig sig) { if (sig == null) return null; if (!recursionCounter.Increment()) return null; PropertySig result = Import(new PropertySig(sig.GetCallingConvention()), sig); recursionCounter.Decrement(); return result; } /// /// Imports a /// /// The sig /// The imported sig or null if input is invalid public LocalSig Import(LocalSig sig) { if (sig == null) return null; if (!recursionCounter.Increment()) return null; LocalSig result = new LocalSig(sig.GetCallingConvention(), (uint)sig.Locals.Count); foreach (var l in sig.Locals.GetSafeEnumerable()) result.Locals.Add(Import(l)); recursionCounter.Decrement(); return result; } /// /// Imports a /// /// The sig /// The imported sig or null if input is invalid public GenericInstMethodSig Import(GenericInstMethodSig sig) { if (sig == null) return null; if (!recursionCounter.Increment()) return null; GenericInstMethodSig result = new GenericInstMethodSig(sig.GetCallingConvention(), (uint)sig.GenericArguments.Count); foreach (var l in sig.GenericArguments.GetSafeEnumerable()) result.GenericArguments.Add(Import(l)); recursionCounter.Decrement(); return result; } /// /// Imports a /// /// The field /// The imported type or null if is invalid public IField Import(IField field) { if (field == null) return null; if (!recursionCounter.Increment()) return null; IField result; MemberRef mr; FieldDef fd; if ((fd = field as FieldDef) != null) result = Import(fd); else if ((mr = field as MemberRef) != null) result = Import(mr); else result = null; recursionCounter.Decrement(); return result; } /// /// Imports a /// /// The method /// The imported method or null if is invalid public IMethod Import(IMethod method) { if (method == null) return null; if (!recursionCounter.Increment()) return null; IMethod result; MethodDef md; MethodSpec ms; MemberRef mr; if ((md = method as MethodDef) != null) result = Import(md); else if ((ms = method as MethodSpec) != null) result = Import(ms); else if ((mr = method as MemberRef) != null) result = Import(mr); else result = null; recursionCounter.Decrement(); return result; } /// /// Imports a as an /// /// The field /// The imported type or null if is invalid public IField Import(FieldDef field) { if (field == null) return null; if (TryToUseFieldDefs && field.Module == module) return field; if (!recursionCounter.Increment()) return null; MemberRef result = module.UpdateRowId(new MemberRefUser(module, field.Name)); result.Signature = Import(field.Signature); result.Class = ImportParent(field.DeclaringType); recursionCounter.Decrement(); return result; } IMemberRefParent ImportParent(TypeDef type) { if (type == null) return null; if (type.IsGlobalModuleType) { var om = type.Module; return module.UpdateRowId(new ModuleRefUser(module, om == null ? null : om.Name)); } return Import(type); } /// /// Imports a as an /// /// The method /// The imported method or null if is invalid public IMethod Import(MethodDef method) { if (method == null) return null; if (TryToUseMethodDefs && method.Module == module) return method; if (!recursionCounter.Increment()) return null; MemberRef result = module.UpdateRowId(new MemberRefUser(module, method.Name)); result.Signature = Import(method.Signature); result.Class = ImportParent(method.DeclaringType); recursionCounter.Decrement(); return result; } /// /// Imports a /// /// The method /// The imported method or null if is invalid public MethodSpec Import(MethodSpec method) { if (method == null) return null; if (!recursionCounter.Increment()) return null; MethodSpec result = module.UpdateRowId(new MethodSpecUser((IMethodDefOrRef)Import(method.Method))); result.Instantiation = Import(method.Instantiation); recursionCounter.Decrement(); return result; } /// /// Imports a /// /// The member ref /// The imported member ref or null if is invalid public MemberRef Import(MemberRef memberRef) { if (memberRef == null) return null; if (!recursionCounter.Increment()) return null; MemberRef result = module.UpdateRowId(new MemberRefUser(module, memberRef.Name)); result.Signature = Import(memberRef.Signature); result.Class = Import(memberRef.Class); if (result.Class == null) // Will be null if memberRef.Class is null or a MethodDef result = null; recursionCounter.Decrement(); return result; } IMemberRefParent Import(IMemberRefParent parent) { var tdr = parent as ITypeDefOrRef; if (tdr != null) { var td = tdr as TypeDef; if (td != null && td.IsGlobalModuleType) { var om = td.Module; return module.UpdateRowId(new ModuleRefUser(module, om == null ? null : om.Name)); } return Import(tdr); } var modRef = parent as ModuleRef; if (modRef != null) return module.UpdateRowId(new ModuleRefUser(module, modRef.Name)); var method = parent as MethodDef; if (method != null) { var dt = method.DeclaringType; return dt == null || dt.Module != module ? null : method; } return null; } } } dnlib-2.1_VS2010/src/DotNet/InterfaceImpl.cs000066400000000000000000000124061325033663500204250ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the InterfaceImpl table /// [DebuggerDisplay("{Interface}")] public abstract class InterfaceImpl : IHasCustomAttribute, IContainsGenericParameter, IHasCustomDebugInformation { /// /// The row id in its table /// protected uint rid; /// public MDToken MDToken { get { return new MDToken(Table.InterfaceImpl, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 5; } } /// /// From column InterfaceImpl.Interface /// public ITypeDefOrRef Interface { get { return @interface; } set { @interface = value; } } /// protected ITypeDefOrRef @interface; /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 5; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } bool IContainsGenericParameter.ContainsGenericParameter { get { return TypeHelper.ContainsGenericParameter(this); } } } /// /// An InterfaceImpl row created by the user and not present in the original .NET file /// public class InterfaceImplUser : InterfaceImpl { /// /// Default constructor /// public InterfaceImplUser() { } /// /// Constructor /// /// The interface the type implements public InterfaceImplUser(ITypeDefOrRef @interface) { this.@interface = @interface; } } /// /// Created from a row in the InterfaceImpl table /// sealed class InterfaceImplMD : InterfaceImpl, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; readonly GenericParamContext gpContext; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.InterfaceImpl, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), gpContext, list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this InterfaceImpl row /// Row ID /// Generic parameter context /// If is null /// If is invalid public InterfaceImplMD(ModuleDefMD readerModule, uint rid, GenericParamContext gpContext) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.InterfaceImplTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("InterfaceImpl rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; this.gpContext = gpContext; uint @interface = readerModule.TablesStream.ReadInterfaceImplRow2(origRid); this.@interface = readerModule.ResolveTypeDefOrRef(@interface, gpContext); } } } dnlib-2.1_VS2010/src/DotNet/MD/000077500000000000000000000000001325033663500156515ustar00rootroot00000000000000dnlib-2.1_VS2010/src/DotNet/MD/BlobStream.cs000066400000000000000000000045351325033663500202410ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.IO; namespace dnlib.DotNet.MD { /// /// Represents the #Blob stream /// public sealed class BlobStream : HeapStream { static readonly byte[] noData = new byte[0]; /// public BlobStream() { } /// public BlobStream(IImageStream imageStream, StreamHeader streamHeader) : base(imageStream, streamHeader) { } /// /// Reads data /// /// Offset of data /// The data or null if invalid offset public byte[] Read(uint offset) { // The CLR has a special check for offset 0. It always interprets it as // 0-length data, even if that first byte isn't 0 at all. if (offset == 0) return noData; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif IImageStream reader; int size = GetReader_NoLock(offset, out reader); if (size < 0) return null; return reader.ReadBytes(size); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads data just like , but returns an empty array if /// offset is invalid /// /// Offset of data /// The data public byte[] ReadNoNull(uint offset) { return Read(offset) ?? noData; } /// /// Creates a new sub stream of the #Blob stream that can access one blob /// /// Offset of blob /// A new stream public IImageStream CreateStream(uint offset) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif IImageStream reader; int size = GetReader_NoLock(offset, out reader); if (size < 0) return MemoryImageStream.CreateEmpty(); return reader.Create((FileOffset)reader.Position, size); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } int GetReader_NoLock(uint offset, out IImageStream reader) { reader = null; if (!IsValidOffset(offset)) return -1; reader = GetReader_NoLock(offset); uint length; if (!reader.ReadCompressedUInt32(out length)) return -1; if (reader.Position + length < length || reader.Position + length > reader.Length) return -1; return (int)length; // length <= 0x1FFFFFFF so this cast does not make it negative } } } dnlib-2.1_VS2010/src/DotNet/MD/CodedToken.cs000066400000000000000000000165141325033663500202260ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet.MD { /// /// Contains all possible coded token classes /// public sealed class CodedToken { /// TypeDefOrRef coded token public static readonly CodedToken TypeDefOrRef = new CodedToken(2, new Table[3] { Table.TypeDef, Table.TypeRef, Table.TypeSpec, }); /// HasConstant coded token public static readonly CodedToken HasConstant = new CodedToken(2, new Table[3] { Table.Field, Table.Param, Table.Property, }); /// HasCustomAttribute coded token public static readonly CodedToken HasCustomAttribute = new CodedToken(5, new Table[24] { Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef, Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef, Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType, Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec, 0, 0, }); /// HasFieldMarshal coded token public static readonly CodedToken HasFieldMarshal = new CodedToken(1, new Table[2] { Table.Field, Table.Param, }); /// HasDeclSecurity coded token public static readonly CodedToken HasDeclSecurity = new CodedToken(2, new Table[3] { Table.TypeDef, Table.Method, Table.Assembly, }); /// MemberRefParent coded token public static readonly CodedToken MemberRefParent = new CodedToken(3, new Table[5] { Table.TypeDef, Table.TypeRef, Table.ModuleRef, Table.Method, Table.TypeSpec, }); /// HasSemantic coded token public static readonly CodedToken HasSemantic = new CodedToken(1, new Table[2] { Table.Event, Table.Property, }); /// MethodDefOrRef coded token public static readonly CodedToken MethodDefOrRef = new CodedToken(1, new Table[2] { Table.Method, Table.MemberRef, }); /// MemberForwarded coded token public static readonly CodedToken MemberForwarded = new CodedToken(1, new Table[2] { Table.Field, Table.Method, }); /// Implementation coded token public static readonly CodedToken Implementation = new CodedToken(2, new Table[3] { Table.File, Table.AssemblyRef, Table.ExportedType, }); /// CustomAttributeType coded token public static readonly CodedToken CustomAttributeType = new CodedToken(3, new Table[4] { 0, 0, Table.Method, Table.MemberRef, }); /// ResolutionScope coded token public static readonly CodedToken ResolutionScope = new CodedToken(2, new Table[4] { Table.Module, Table.ModuleRef, Table.AssemblyRef, Table.TypeRef, }); /// TypeOrMethodDef coded token public static readonly CodedToken TypeOrMethodDef = new CodedToken(1, new Table[2] { Table.TypeDef, Table.Method, }); /// HasCustomDebugInformation coded token public static readonly CodedToken HasCustomDebugInformation = new CodedToken(5, new Table[27] { Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef, Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef, Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType, Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec, Table.Document, Table.LocalScope, Table.LocalVariable, Table.LocalConstant, Table.ImportScope, }); readonly Table[] tableTypes; readonly int bits; readonly int mask; /// /// Returns all types of tables /// public Table[] TableTypes { get { return tableTypes; } } /// /// Returns the number of bits that is used to encode table type /// public int Bits { get { return bits; } } /// /// Constructor /// /// Number of bits used to encode token type /// All table types internal CodedToken(int bits, Table[] tableTypes) { this.bits = bits; this.mask = (1 << bits) - 1; this.tableTypes = tableTypes; } /// /// Encodes a token /// /// The token /// Coded token /// public uint Encode(MDToken token) { return Encode(token.Raw); } /// /// Encodes a token /// /// The token /// Coded token /// public uint Encode(uint token) { uint codedToken; Encode(token, out codedToken); return codedToken; } /// /// Encodes a token /// /// The token /// Coded token /// true if successful public bool Encode(MDToken token, out uint codedToken) { return Encode(token.Raw, out codedToken); } /// /// Encodes a token /// /// The token /// Coded token /// true if successful public bool Encode(uint token, out uint codedToken) { int index = Array.IndexOf(tableTypes, MDToken.ToTable(token)); if (index < 0) { codedToken = uint.MaxValue; return false; } // This shift can never overflow a uint since bits < 8 (it's at most 5), and // ToRid() returns an integer <= 0x00FFFFFF. codedToken = (MDToken.ToRID(token) << bits) | (uint)index; return true; } /// /// Decodes a coded token /// /// The coded token /// Decoded token or 0 on failure /// public MDToken Decode2(uint codedToken) { uint token; Decode(codedToken, out token); return new MDToken(token); } /// /// Decodes a coded token /// /// The coded token /// Decoded token or 0 on failure /// public uint Decode(uint codedToken) { uint token; Decode(codedToken, out token); return token; } /// /// Decodes a coded token /// /// The coded token /// Decoded token /// true if successful public bool Decode(uint codedToken, out MDToken token) { uint decodedToken; bool result = Decode(codedToken, out decodedToken); token = new MDToken(decodedToken); return result; } /// /// Decodes a coded token /// /// The coded token /// Decoded token /// true if successful public bool Decode(uint codedToken, out uint token) { uint rid = codedToken >> bits; int index = (int)(codedToken & mask); if (rid > MDToken.RID_MAX || index >= tableTypes.Length) { token = 0; return false; } token = ((uint)tableTypes[index] << MDToken.TABLE_SHIFT) | rid; return true; } } } dnlib-2.1_VS2010/src/DotNet/MD/ColumnInfo.cs000066400000000000000000000054701325033663500202570ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.IO; using dnlib.IO; namespace dnlib.DotNet.MD { /// /// Info about one column in a MD table /// [DebuggerDisplay("{offset} {size} {name}")] public sealed class ColumnInfo { readonly byte index; byte offset; readonly ColumnSize columnSize; byte size; readonly string name; /// /// Gets the column index /// public int Index { get { return index; } } /// /// Returns the column offset within the table row /// public int Offset { get { return offset; } internal set { offset = (byte)value; } } /// /// Returns the column size /// public int Size { get { return size; } internal set { size = (byte)value; } } /// /// Returns the column name /// public string Name { get { return name; } } /// /// Returns the ColumnSize enum value /// public ColumnSize ColumnSize { get { return columnSize; } } /// /// Constructor /// /// Column index /// The column name /// Column size public ColumnInfo(byte index, string name, ColumnSize columnSize) { this.index = index; this.name = name; this.columnSize = columnSize; } /// /// Constructor /// /// Column index /// The column name /// Column size /// Offset of column /// Size of column public ColumnInfo(byte index, string name, ColumnSize columnSize, byte offset, byte size) { this.index = index; this.name = name; this.columnSize = columnSize; this.offset = offset; this.size = size; } /// /// Reads the column /// /// A reader positioned on this column /// The column value public uint Read(IBinaryReader reader) { switch (size) { case 1: return reader.ReadByte(); case 2: return reader.ReadUInt16(); case 4: return reader.ReadUInt32(); default: throw new InvalidOperationException("Invalid column size"); } } /// /// Writes a column /// /// The writer position on this column /// The column value public void Write(BinaryWriter writer, uint value) { switch (size) { case 1: writer.Write((byte)value); break; case 2: writer.Write((ushort)value); break; case 4: writer.Write(value); break; default: throw new InvalidOperationException("Invalid column size"); } } } } dnlib-2.1_VS2010/src/DotNet/MD/ColumnSize.cs000066400000000000000000000120751325033663500202750ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.MD { /// /// MD table column size /// public enum ColumnSize : byte { /// RID into Module table Module, /// RID into TypeRef table TypeRef, /// RID into TypeDef table TypeDef, /// RID into FieldPtr table FieldPtr, /// RID into Field table Field, /// RID into MethodPtr table MethodPtr, /// RID into Method table Method, /// RID into ParamPtr table ParamPtr, /// RID into Param table Param, /// RID into InterfaceImpl table InterfaceImpl, /// RID into MemberRef table MemberRef, /// RID into Constant table Constant, /// RID into CustomAttribute table CustomAttribute, /// RID into FieldMarshal table FieldMarshal, /// RID into DeclSecurity table DeclSecurity, /// RID into ClassLayout table ClassLayout, /// RID into FieldLayout table FieldLayout, /// RID into StandAloneSig table StandAloneSig, /// RID into EventMap table EventMap, /// RID into EventPtr table EventPtr, /// RID into Event table Event, /// RID into PropertyMap table PropertyMap, /// RID into PropertyPtr table PropertyPtr, /// RID into Property table Property, /// RID into MethodSemantics table MethodSemantics, /// RID into MethodImpl table MethodImpl, /// RID into ModuleRef table ModuleRef, /// RID into TypeSpec table TypeSpec, /// RID into ImplMap table ImplMap, /// RID into FieldRVA table FieldRVA, /// RID into ENCLog table ENCLog, /// RID into ENCMap table ENCMap, /// RID into Assembly table Assembly, /// RID into AssemblyProcessor table AssemblyProcessor, /// RID into AssemblyOS table AssemblyOS, /// RID into AssemblyRef table AssemblyRef, /// RID into AssemblyRefProcessor table AssemblyRefProcessor, /// RID into AssemblyRefOS table AssemblyRefOS, /// RID into File table File, /// RID into ExportedType table ExportedType, /// RID into ManifestResource table ManifestResource, /// RID into NestedClass table NestedClass, /// RID into GenericParam table GenericParam, /// RID into MethodSpec table MethodSpec, /// RID into GenericParamConstraint table GenericParamConstraint, /// RID into Document table Document = 0x30, /// RID into MethodDebugInformation table MethodDebugInformation, /// RID into LocalScope table LocalScope, /// RID into LocalVariable table LocalVariable, /// RID into LocalConstant table LocalConstant, /// RID into ImportScope table ImportScope, /// RID into StateMachineMethod table StateMachineMethod, /// RID into CustomDebugInformation table CustomDebugInformation, /// 8-bit byte Byte = 0x40, /// 16-bit signed int Int16, /// 16-bit unsigned int UInt16, /// 32-bit signed int Int32, /// 32-bit unsigned int UInt32, /// Index into #Strings stream Strings, /// Index into #GUID stream GUID, /// Index into #Blob stream Blob, /// TypeDefOrRef encoded token TypeDefOrRef, /// HasConstant encoded token HasConstant, /// HasCustomAttribute encoded token HasCustomAttribute, /// HasFieldMarshal encoded token HasFieldMarshal, /// HasDeclSecurity encoded token HasDeclSecurity, /// MemberRefParent encoded token MemberRefParent, /// HasSemantic encoded token HasSemantic, /// MethodDefOrRef encoded token MethodDefOrRef, /// MemberForwarded encoded token MemberForwarded, /// Implementation encoded token Implementation, /// CustomAttributeType encoded token CustomAttributeType, /// ResolutionScope encoded token ResolutionScope, /// TypeOrMethodDef encoded token TypeOrMethodDef, /// HasCustomDebugInformation encoded token HasCustomDebugInformation, } } dnlib-2.1_VS2010/src/DotNet/MD/ComImageFlags.cs000066400000000000000000000020171325033663500206360ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet.MD { /// /// See COMIMAGE_FLAGS_XXX in CorHdr.h in the Windows SDK /// [Flags] public enum ComImageFlags : uint { /// /// See COMIMAGE_FLAGS_ILONLY in the Windows SDK /// ILOnly = 1, /// /// See COMIMAGE_FLAGS_32BITREQUIRED in the Windows SDK /// _32BitRequired = 2, /// /// Set if a native header exists (COMIMAGE_FLAGS_IL_LIBRARY) /// ILLibrary = 4, /// /// See COMIMAGE_FLAGS_STRONGNAMESIGNED in the Windows SDK /// StrongNameSigned = 8, /// /// See COMIMAGE_FLAGS_NATIVE_ENTRYPOINT in the Windows SDK /// NativeEntryPoint = 0x10, /// /// See COMIMAGE_FLAGS_TRACKDEBUGDATA in the Windows SDK /// TrackDebugData = 0x10000, /// /// See COMIMAGE_FLAGS_32BITPREFERRED in the Windows SDK /// _32BitPreferred = 0x20000, } } dnlib-2.1_VS2010/src/DotNet/MD/CompressedMetaData.cs000066400000000000000000000234311325033663500217100ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using dnlib.IO; using dnlib.PE; using dnlib.Threading; namespace dnlib.DotNet.MD { /// /// Used when a #~ stream is present in the metadata /// sealed class CompressedMetaData : MetaData { /// public override bool IsCompressed { get { return true; } } /// public CompressedMetaData(IPEImage peImage, ImageCor20Header cor20Header, MetaDataHeader mdHeader) : base(peImage, cor20Header, mdHeader) { } /// internal CompressedMetaData(MetaDataHeader mdHeader, bool isStandalonePortablePdb) : base(mdHeader, isStandalonePortablePdb) { } static CompressedMetaData() { var windir = Environment.GetEnvironmentVariable("WINDIR"); if (!string.IsNullOrEmpty(windir)) { var baseDir = Path.Combine(windir, "assembly"); nativeImages40 = Path.Combine(baseDir, "NativeImages_v4.0.30319"); } } static string nativeImages40; static HotHeapVersion GetHotHeapVersion(string fileName, string version) { // Some .NET 2.0 assemblies are stored in the 4.0 GAC. The version is not easily // detectable from the data in the image so check the path. if (nativeImages40 != null && fileName != null && fileName.StartsWith(nativeImages40, StringComparison.OrdinalIgnoreCase)) return HotHeapVersion.CLR40; if (version.StartsWith(MDHeaderRuntimeVersion.MS_CLR_20_PREFIX)) return HotHeapVersion.CLR20; if (version.StartsWith(MDHeaderRuntimeVersion.MS_CLR_40_PREFIX)) return HotHeapVersion.CLR40; return HotHeapVersion.CLR40; } /// protected override void InitializeInternal(IImageStream mdStream) { var hotHeapVersion = peImage == null ? HotHeapVersion.CLR20 : GetHotHeapVersion(peImage.FileName, mdHeader.VersionString); bool disposeOfMdStream = false; IImageStream imageStream = null, fullStream = null; DotNetStream dns = null; List hotStreams = null; HotStream hotStream = null; var newAllStreams = new List(allStreams); try { if (peImage != null) { Debug.Assert(mdStream == null); Debug.Assert(cor20Header != null); var mdOffset = peImage.ToFileOffset(cor20Header.MetaData.VirtualAddress); mdStream = peImage.CreateStream(mdOffset, cor20Header.MetaData.Size); disposeOfMdStream = true; } else Debug.Assert(mdStream != null); for (int i = mdHeader.StreamHeaders.Count - 1; i >= 0; i--) { var sh = mdHeader.StreamHeaders[i]; imageStream = mdStream.Create((FileOffset)sh.Offset, sh.StreamSize); switch (sh.Name) { case "#Strings": if (stringsStream == null) { stringsStream = new StringsStream(imageStream, sh); imageStream = null; newAllStreams.Add(stringsStream); continue; } break; case "#US": if (usStream == null) { usStream = new USStream(imageStream, sh); imageStream = null; newAllStreams.Add(usStream); continue; } break; case "#Blob": if (blobStream == null) { blobStream = new BlobStream(imageStream, sh); imageStream = null; newAllStreams.Add(blobStream); continue; } break; case "#GUID": if (guidStream == null) { guidStream = new GuidStream(imageStream, sh); imageStream = null; newAllStreams.Add(guidStream); continue; } break; case "#~": if (tablesStream == null) { tablesStream = new TablesStream(imageStream, sh); imageStream = null; newAllStreams.Add(tablesStream); continue; } break; case "#!": if (peImage == null) break; if (hotStreams == null) hotStreams = new List(); fullStream = peImage.CreateFullStream(); hotStream = HotStream.Create(hotHeapVersion, imageStream, sh, fullStream, mdStream.FileOffset + sh.Offset); fullStream = null; hotStreams.Add(hotStream); newAllStreams.Add(hotStream); hotStream = null; imageStream = null; continue; case "#Pdb": if (isStandalonePortablePdb && pdbStream == null) { pdbStream = new PdbStream(imageStream, sh); imageStream = null; allStreams.Add(pdbStream); continue; } break; } dns = new DotNetStream(imageStream, sh); imageStream = null; newAllStreams.Add(dns); dns = null; } } finally { if (disposeOfMdStream) mdStream.Dispose(); if (imageStream != null) imageStream.Dispose(); if (fullStream != null) fullStream.Dispose(); if (dns != null) dns.Dispose(); if (hotStream != null) hotStream.Dispose(); newAllStreams.Reverse(); allStreams = ThreadSafeListCreator.MakeThreadSafe(newAllStreams); } if (tablesStream == null) throw new BadImageFormatException("Missing MD stream"); if (hotStreams != null) { hotStreams.Reverse(); InitializeHotStreams(hotStreams); } if (pdbStream != null) tablesStream.Initialize(pdbStream.TypeSystemTableRows); else tablesStream.Initialize(null); } int GetPointerSize() { if (peImage == null) return 4; return peImage.ImageNTHeaders.OptionalHeader.Magic == 0x10B ? 4 : 8; } void InitializeHotStreams(IList hotStreams) { if (hotStreams == null || hotStreams.Count == 0) return; // If this is a 32-bit image, make sure that we emulate this by masking // all base offsets to 32 bits. long offsetMask = GetPointerSize() == 8 ? -1L : uint.MaxValue; // It's always the last one found that is used var hotTable = hotStreams[hotStreams.Count - 1].HotTableStream; if (hotTable != null) { hotTable.Initialize(offsetMask); tablesStream.HotTableStream = hotTable; } HotHeapStream hotStrings = null, hotBlob = null, hotGuid = null, hotUs = null; for (int i = hotStreams.Count - 1; i >= 0; i--) { var hotStream = hotStreams[i]; var hotHeapStreams = hotStream.HotHeapStreams; if (hotHeapStreams == null) continue; // It's always the last one found that is used for (int j = hotHeapStreams.Count - 1; j >= 0; j--) { var hotHeap = hotHeapStreams[j]; switch (hotHeap.HeapType) { case HeapType.Strings: if (hotStrings == null) { hotHeap.Initialize(offsetMask); hotStrings = hotHeap; } break; case HeapType.Guid: if (hotGuid == null) { hotHeap.Initialize(offsetMask); hotGuid = hotHeap; } break; case HeapType.Blob: if (hotBlob == null) { hotHeap.Initialize(offsetMask); hotBlob = hotHeap; } break; case HeapType.US: if (hotUs == null) { hotHeap.Initialize(offsetMask); hotUs = hotHeap; } break; } } } InitializeNonExistentHeaps(); stringsStream.HotHeapStream = hotStrings; guidStream.HotHeapStream = hotGuid; blobStream.HotHeapStream = hotBlob; usStream.HotHeapStream = hotUs; } /// public override RidList GetFieldRidList(uint typeDefRid) { return GetRidList(tablesStream.TypeDefTable, typeDefRid, 4, tablesStream.FieldTable); } /// public override RidList GetMethodRidList(uint typeDefRid) { return GetRidList(tablesStream.TypeDefTable, typeDefRid, 5, tablesStream.MethodTable); } /// public override RidList GetParamRidList(uint methodRid) { return GetRidList(tablesStream.MethodTable, methodRid, 5, tablesStream.ParamTable); } /// public override RidList GetEventRidList(uint eventMapRid) { return GetRidList(tablesStream.EventMapTable, eventMapRid, 1, tablesStream.EventTable); } /// public override RidList GetPropertyRidList(uint propertyMapRid) { return GetRidList(tablesStream.PropertyMapTable, propertyMapRid, 1, tablesStream.PropertyTable); } /// /// Gets a rid list (eg. field list) /// /// Source table, eg. TypeDef /// Row ID in /// Column index in , eg. 4 for TypeDef.FieldList /// Destination table, eg. Field /// A new instance RidList GetRidList(MDTable tableSource, uint tableSourceRid, int colIndex, MDTable tableDest) { var column = tableSource.TableInfo.Columns[colIndex]; uint startRid, nextListRid; bool hasNext; #if THREAD_SAFE tablesStream.theLock.EnterWriteLock(); try { #endif if (!tablesStream.ReadColumn_NoLock(tableSource, tableSourceRid, column, out startRid)) return RidList.Empty; hasNext = tablesStream.ReadColumn_NoLock(tableSource, tableSourceRid + 1, column, out nextListRid); #if THREAD_SAFE } finally { tablesStream.theLock.ExitWriteLock(); } #endif uint lastRid = tableDest.Rows + 1; if (startRid == 0 || startRid >= lastRid) return RidList.Empty; uint endRid = hasNext ? nextListRid : lastRid; if (endRid < startRid) endRid = startRid; if (endRid > lastRid) endRid = lastRid; return new ContiguousRidList(startRid, endRid - startRid); } /// protected override uint BinarySearch_NoLock(MDTable tableSource, int keyColIndex, uint key) { var keyColumn = tableSource.TableInfo.Columns[keyColIndex]; uint ridLo = 1, ridHi = tableSource.Rows; while (ridLo <= ridHi) { uint rid = (ridLo + ridHi) / 2; uint key2; if (!tablesStream.ReadColumn_NoLock(tableSource, rid, keyColumn, out key2)) break; // Never happens since rid is valid if (key == key2) return rid; if (key2 > key) ridHi = rid - 1; else ridLo = rid + 1; } return 0; } } } dnlib-2.1_VS2010/src/DotNet/MD/DotNetStream.cs000066400000000000000000000112541325033663500205540ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using dnlib.IO; using dnlib.Threading; namespace dnlib.DotNet.MD { /// /// .NET metadata stream /// [DebuggerDisplay("{imageStream.Length} {streamHeader.Name}")] public class DotNetStream : IFileSection, IDisposable { /// /// Reader that can access the whole stream /// protected IImageStream imageStream; /// /// null if it wasn't present in the file /// StreamHeader streamHeader; /// public FileOffset StartOffset { get { return imageStream.FileOffset; } } /// public FileOffset EndOffset { get { return imageStream.FileOffset + imageStream.Length; } } /// /// Gets the length of the internal .NET blob stream /// public long ImageStreamLength { get { return imageStream.Length; } } /// /// Gets the stream header /// public StreamHeader StreamHeader { get { return streamHeader; } } /// /// Gets the name of the stream /// public string Name { get { return streamHeader == null ? string.Empty : streamHeader.Name; } } /// /// Returns a cloned of the internal .NET blob stream. /// /// A new instance public IImageStream GetClonedImageStream() { return imageStream.Clone(); } /// /// Default constructor /// public DotNetStream() { this.imageStream = MemoryImageStream.CreateEmpty(); this.streamHeader = null; } /// /// Constructor /// /// Stream data /// The stream header public DotNetStream(IImageStream imageStream, StreamHeader streamHeader) { this.imageStream = imageStream; this.streamHeader = streamHeader; } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose method /// /// true if called by protected virtual void Dispose(bool disposing) { if (disposing) { var ims = imageStream; if (ims != null) ims.Dispose(); imageStream = null; streamHeader = null; } } /// /// Checks whether an index is valid /// /// The index /// true if the index is valid public virtual bool IsValidIndex(uint index) { return IsValidOffset(index); } /// /// Check whether an offset is within the stream /// /// Stream offset /// true if the offset is valid public bool IsValidOffset(uint offset) { return offset == 0 || offset < imageStream.Length; } /// /// Check whether an offset is within the stream /// /// Stream offset /// Size of data /// true if the offset is valid public bool IsValidOffset(uint offset, int size) { if (size == 0) return IsValidOffset(offset); return size > 0 && (long)offset + (uint)size <= imageStream.Length; } } /// /// Base class of #US, #Strings, #Blob, and #GUID classes /// public abstract class HeapStream : DotNetStream { HotHeapStream hotHeapStream; #if THREAD_SAFE internal readonly Lock theLock = Lock.Create(); #endif /// /// Gets/sets the instance /// internal HotHeapStream HotHeapStream { set { hotHeapStream = value; } } /// protected HeapStream() { } /// protected HeapStream(IImageStream imageStream, StreamHeader streamHeader) : base(imageStream, streamHeader) { } /// /// Gets the heap reader and initializes its position /// /// Offset in the heap. If it's the #GUID heap, this should /// be the offset of the GUID, not its index /// The heap reader protected IImageStream GetReader_NoLock(uint offset) { var stream = hotHeapStream == null ? null : hotHeapStream.GetBlobReader(offset); if (stream == null) { stream = imageStream; stream.Position = offset; } return stream; } /// protected override void Dispose(bool disposing) { if (disposing) { var hhs = hotHeapStream; if (hhs != null) hhs.Dispose(); hotHeapStream = null; } base.Dispose(disposing); } } } dnlib-2.1_VS2010/src/DotNet/MD/DotNetTableSizes.cs000066400000000000000000000500271325033663500213670ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; namespace dnlib.DotNet.MD { /// /// Initializes .NET table row sizes /// public sealed class DotNetTableSizes { bool bigStrings; bool bigGuid; bool bigBlob; TableInfo[] tableInfos; internal static bool IsSystemTable(Table table) { return table < Table.Document; } /// /// Initializes the table sizes /// /// true if #Strings size >= 0x10000 /// true if #GUID size >= 0x10000 /// true if #Blob size >= 0x10000 /// Count of rows in each table /// Count of rows in each table (debug tables) public void InitializeSizes(bool bigStrings, bool bigGuid, bool bigBlob, IList systemRowCounts, IList debugRowCounts) { this.bigStrings = bigStrings; this.bigGuid = bigGuid; this.bigBlob = bigBlob; foreach (var tableInfo in tableInfos) { var rowCounts = IsSystemTable(tableInfo.Table) ? systemRowCounts : debugRowCounts; int colOffset = 0; foreach (var colInfo in tableInfo.Columns) { colInfo.Offset = colOffset; var colSize = GetSize(colInfo.ColumnSize, rowCounts); colInfo.Size = colSize; colOffset += colSize; } tableInfo.RowSize = colOffset; } } int GetSize(ColumnSize columnSize, IList rowCounts) { if (ColumnSize.Module <= columnSize && columnSize <= ColumnSize.CustomDebugInformation) { int table = (int)(columnSize - ColumnSize.Module); uint count = table >= rowCounts.Count ? 0 : rowCounts[table]; return count > 0xFFFF ? 4 : 2; } else if (ColumnSize.TypeDefOrRef <= columnSize && columnSize <= ColumnSize.HasCustomDebugInformation) { CodedToken info; switch (columnSize) { case ColumnSize.TypeDefOrRef: info = CodedToken.TypeDefOrRef; break; case ColumnSize.HasConstant: info = CodedToken.HasConstant; break; case ColumnSize.HasCustomAttribute: info = CodedToken.HasCustomAttribute; break; case ColumnSize.HasFieldMarshal: info = CodedToken.HasFieldMarshal; break; case ColumnSize.HasDeclSecurity: info = CodedToken.HasDeclSecurity; break; case ColumnSize.MemberRefParent: info = CodedToken.MemberRefParent; break; case ColumnSize.HasSemantic: info = CodedToken.HasSemantic; break; case ColumnSize.MethodDefOrRef: info = CodedToken.MethodDefOrRef; break; case ColumnSize.MemberForwarded: info = CodedToken.MemberForwarded; break; case ColumnSize.Implementation: info = CodedToken.Implementation; break; case ColumnSize.CustomAttributeType:info = CodedToken.CustomAttributeType; break; case ColumnSize.ResolutionScope: info = CodedToken.ResolutionScope; break; case ColumnSize.TypeOrMethodDef: info = CodedToken.TypeOrMethodDef; break; case ColumnSize.HasCustomDebugInformation:info = CodedToken.HasCustomDebugInformation; break; default: throw new InvalidOperationException(string.Format("Invalid ColumnSize: {0}", columnSize)); } uint maxRows = 0; foreach (var tableType in info.TableTypes) { int index = (int)tableType; var tableRows = index >= rowCounts.Count ? 0 : rowCounts[index]; if (tableRows > maxRows) maxRows = tableRows; } // Can't overflow since maxRows <= 0x00FFFFFF and info.Bits < 8 uint finalRows = maxRows << info.Bits; return finalRows > 0xFFFF ? 4 : 2; } else { switch (columnSize) { case ColumnSize.Byte: return 1; case ColumnSize.Int16: return 2; case ColumnSize.UInt16: return 2; case ColumnSize.Int32: return 4; case ColumnSize.UInt32: return 4; case ColumnSize.Strings:return bigStrings ? 4 : 2; case ColumnSize.GUID: return bigGuid ? 4 : 2; case ColumnSize.Blob: return bigBlob ? 4 : 2; } } throw new InvalidOperationException(string.Format("Invalid ColumnSize: {0}", columnSize)); } /// /// Creates the table infos /// /// Major table version /// Minor table version /// All table infos (not completely initialized) public TableInfo[] CreateTables(byte majorVersion, byte minorVersion) { int maxPresentTables; return CreateTables(majorVersion, minorVersion, out maxPresentTables); } internal const int normalMaxTables = (int)Table.CustomDebugInformation + 1; /// /// Creates the table infos /// /// Major table version /// Minor table version /// Initialized to max present tables (eg. 42 or 45) /// All table infos (not completely initialized) public TableInfo[] CreateTables(byte majorVersion, byte minorVersion, out int maxPresentTables) { maxPresentTables = (majorVersion == 1 && minorVersion == 0) ? (int)Table.NestedClass + 1 : normalMaxTables; var tableInfos = new TableInfo[normalMaxTables]; tableInfos[(int)Table.Module] = new TableInfo(Table.Module, "Module", new ColumnInfo[] { new ColumnInfo(0, "Generation", ColumnSize.UInt16), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "Mvid", ColumnSize.GUID), new ColumnInfo(3, "EncId", ColumnSize.GUID), new ColumnInfo(4, "EncBaseId", ColumnSize.GUID), }); tableInfos[(int)Table.TypeRef] = new TableInfo(Table.TypeRef, "TypeRef", new ColumnInfo[] { new ColumnInfo(0, "ResolutionScope", ColumnSize.ResolutionScope), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "Namespace", ColumnSize.Strings), }); tableInfos[(int)Table.TypeDef] = new TableInfo(Table.TypeDef, "TypeDef", new ColumnInfo[] { new ColumnInfo(0, "Flags", ColumnSize.UInt32), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "Namespace", ColumnSize.Strings), new ColumnInfo(3, "Extends", ColumnSize.TypeDefOrRef), new ColumnInfo(4, "FieldList", ColumnSize.Field), new ColumnInfo(5, "MethodList", ColumnSize.Method), }); tableInfos[(int)Table.FieldPtr] = new TableInfo(Table.FieldPtr, "FieldPtr", new ColumnInfo[] { new ColumnInfo(0, "Field", ColumnSize.Field), }); tableInfos[(int)Table.Field] = new TableInfo(Table.Field, "Field", new ColumnInfo[] { new ColumnInfo(0, "Flags", ColumnSize.UInt16), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "Signature", ColumnSize.Blob), }); tableInfos[(int)Table.MethodPtr] = new TableInfo(Table.MethodPtr, "MethodPtr", new ColumnInfo[] { new ColumnInfo(0, "Method", ColumnSize.Method), }); tableInfos[(int)Table.Method] = new TableInfo(Table.Method, "Method", new ColumnInfo[] { new ColumnInfo(0, "RVA", ColumnSize.UInt32), new ColumnInfo(1, "ImplFlags", ColumnSize.UInt16), new ColumnInfo(2, "Flags", ColumnSize.UInt16), new ColumnInfo(3, "Name", ColumnSize.Strings), new ColumnInfo(4, "Signature", ColumnSize.Blob), new ColumnInfo(5, "ParamList", ColumnSize.Param), }); tableInfos[(int)Table.ParamPtr] = new TableInfo(Table.ParamPtr, "ParamPtr", new ColumnInfo[] { new ColumnInfo(0, "Param", ColumnSize.Param), }); tableInfos[(int)Table.Param] = new TableInfo(Table.Param, "Param", new ColumnInfo[] { new ColumnInfo(0, "Flags", ColumnSize.UInt16), new ColumnInfo(1, "Sequence", ColumnSize.UInt16), new ColumnInfo(2, "Name", ColumnSize.Strings), }); tableInfos[(int)Table.InterfaceImpl] = new TableInfo(Table.InterfaceImpl, "InterfaceImpl", new ColumnInfo[] { new ColumnInfo(0, "Class", ColumnSize.TypeDef), new ColumnInfo(1, "Interface", ColumnSize.TypeDefOrRef), }); tableInfos[(int)Table.MemberRef] = new TableInfo(Table.MemberRef, "MemberRef", new ColumnInfo[] { new ColumnInfo(0, "Class", ColumnSize.MemberRefParent), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "Signature", ColumnSize.Blob), }); tableInfos[(int)Table.Constant] = new TableInfo(Table.Constant, "Constant", new ColumnInfo[] { new ColumnInfo(0, "Type", ColumnSize.Byte), new ColumnInfo(1, "Padding", ColumnSize.Byte), new ColumnInfo(2, "Parent", ColumnSize.HasConstant), new ColumnInfo(3, "Value", ColumnSize.Blob), }); tableInfos[(int)Table.CustomAttribute] = new TableInfo(Table.CustomAttribute, "CustomAttribute", new ColumnInfo[] { new ColumnInfo(0, "Parent", ColumnSize.HasCustomAttribute), new ColumnInfo(1, "Type", ColumnSize.CustomAttributeType), new ColumnInfo(2, "Value", ColumnSize.Blob), }); tableInfos[(int)Table.FieldMarshal] = new TableInfo(Table.FieldMarshal, "FieldMarshal", new ColumnInfo[] { new ColumnInfo(0, "Parent", ColumnSize.HasFieldMarshal), new ColumnInfo(1, "NativeType", ColumnSize.Blob), }); tableInfos[(int)Table.DeclSecurity] = new TableInfo(Table.DeclSecurity, "DeclSecurity", new ColumnInfo[] { new ColumnInfo(0, "Action", ColumnSize.Int16), new ColumnInfo(1, "Parent", ColumnSize.HasDeclSecurity), new ColumnInfo(2, "PermissionSet", ColumnSize.Blob), }); tableInfos[(int)Table.ClassLayout] = new TableInfo(Table.ClassLayout, "ClassLayout", new ColumnInfo[] { new ColumnInfo(0, "PackingSize", ColumnSize.UInt16), new ColumnInfo(1, "ClassSize", ColumnSize.UInt32), new ColumnInfo(2, "Parent", ColumnSize.TypeDef), }); tableInfos[(int)Table.FieldLayout] = new TableInfo(Table.FieldLayout, "FieldLayout", new ColumnInfo[] { new ColumnInfo(0, "OffSet", ColumnSize.UInt32), new ColumnInfo(1, "Field", ColumnSize.Field), }); tableInfos[(int)Table.StandAloneSig] = new TableInfo(Table.StandAloneSig, "StandAloneSig", new ColumnInfo[] { new ColumnInfo(0, "Signature", ColumnSize.Blob), }); tableInfos[(int)Table.EventMap] = new TableInfo(Table.EventMap, "EventMap", new ColumnInfo[] { new ColumnInfo(0, "Parent", ColumnSize.TypeDef), new ColumnInfo(1, "EventList", ColumnSize.Event), }); tableInfos[(int)Table.EventPtr] = new TableInfo(Table.EventPtr, "EventPtr", new ColumnInfo[] { new ColumnInfo(0, "Event", ColumnSize.Event), }); tableInfos[(int)Table.Event] = new TableInfo(Table.Event, "Event", new ColumnInfo[] { new ColumnInfo(0, "EventFlags", ColumnSize.UInt16), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "EventType", ColumnSize.TypeDefOrRef), }); tableInfos[(int)Table.PropertyMap] = new TableInfo(Table.PropertyMap, "PropertyMap", new ColumnInfo[] { new ColumnInfo(0, "Parent", ColumnSize.TypeDef), new ColumnInfo(1, "PropertyList", ColumnSize.Property), }); tableInfos[(int)Table.PropertyPtr] = new TableInfo(Table.PropertyPtr, "PropertyPtr", new ColumnInfo[] { new ColumnInfo(0, "Property", ColumnSize.Property), }); tableInfos[(int)Table.Property] = new TableInfo(Table.Property, "Property", new ColumnInfo[] { new ColumnInfo(0, "PropFlags", ColumnSize.UInt16), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "Type", ColumnSize.Blob), }); tableInfos[(int)Table.MethodSemantics] = new TableInfo(Table.MethodSemantics, "MethodSemantics", new ColumnInfo[] { new ColumnInfo(0, "Semantic", ColumnSize.UInt16), new ColumnInfo(1, "Method", ColumnSize.Method), new ColumnInfo(2, "Association", ColumnSize.HasSemantic), }); tableInfos[(int)Table.MethodImpl] = new TableInfo(Table.MethodImpl, "MethodImpl", new ColumnInfo[] { new ColumnInfo(0, "Class", ColumnSize.TypeDef), new ColumnInfo(1, "MethodBody", ColumnSize.MethodDefOrRef), new ColumnInfo(2, "MethodDeclaration", ColumnSize.MethodDefOrRef), }); tableInfos[(int)Table.ModuleRef] = new TableInfo(Table.ModuleRef, "ModuleRef", new ColumnInfo[] { new ColumnInfo(0, "Name", ColumnSize.Strings), }); tableInfos[(int)Table.TypeSpec] = new TableInfo(Table.TypeSpec, "TypeSpec", new ColumnInfo[] { new ColumnInfo(0, "Signature", ColumnSize.Blob), }); tableInfos[(int)Table.ImplMap] = new TableInfo(Table.ImplMap, "ImplMap", new ColumnInfo[] { new ColumnInfo(0, "MappingFlags", ColumnSize.UInt16), new ColumnInfo(1, "MemberForwarded", ColumnSize.MemberForwarded), new ColumnInfo(2, "ImportName", ColumnSize.Strings), new ColumnInfo(3, "ImportScope", ColumnSize.ModuleRef), }); tableInfos[(int)Table.FieldRVA] = new TableInfo(Table.FieldRVA, "FieldRVA", new ColumnInfo[] { new ColumnInfo(0, "RVA", ColumnSize.UInt32), new ColumnInfo(1, "Field", ColumnSize.Field), }); tableInfos[(int)Table.ENCLog] = new TableInfo(Table.ENCLog, "ENCLog", new ColumnInfo[] { new ColumnInfo(0, "Token", ColumnSize.UInt32), new ColumnInfo(1, "FuncCode", ColumnSize.UInt32), }); tableInfos[(int)Table.ENCMap] = new TableInfo(Table.ENCMap, "ENCMap", new ColumnInfo[] { new ColumnInfo(0, "Token", ColumnSize.UInt32), }); tableInfos[(int)Table.Assembly] = new TableInfo(Table.Assembly, "Assembly", new ColumnInfo[] { new ColumnInfo(0, "HashAlgId", ColumnSize.UInt32), new ColumnInfo(1, "MajorVersion", ColumnSize.UInt16), new ColumnInfo(2, "MinorVersion", ColumnSize.UInt16), new ColumnInfo(3, "BuildNumber", ColumnSize.UInt16), new ColumnInfo(4, "RevisionNumber", ColumnSize.UInt16), new ColumnInfo(5, "Flags", ColumnSize.UInt32), new ColumnInfo(6, "PublicKey", ColumnSize.Blob), new ColumnInfo(7, "Name", ColumnSize.Strings), new ColumnInfo(8, "Locale", ColumnSize.Strings), }); tableInfos[(int)Table.AssemblyProcessor] = new TableInfo(Table.AssemblyProcessor, "AssemblyProcessor", new ColumnInfo[] { new ColumnInfo(0, "Processor", ColumnSize.UInt32), }); tableInfos[(int)Table.AssemblyOS] = new TableInfo(Table.AssemblyOS, "AssemblyOS", new ColumnInfo[] { new ColumnInfo(0, "OSPlatformId", ColumnSize.UInt32), new ColumnInfo(1, "OSMajorVersion", ColumnSize.UInt32), new ColumnInfo(2, "OSMinorVersion", ColumnSize.UInt32), }); tableInfos[(int)Table.AssemblyRef] = new TableInfo(Table.AssemblyRef, "AssemblyRef", new ColumnInfo[] { new ColumnInfo(0, "MajorVersion", ColumnSize.UInt16), new ColumnInfo(1, "MinorVersion", ColumnSize.UInt16), new ColumnInfo(2, "BuildNumber", ColumnSize.UInt16), new ColumnInfo(3, "RevisionNumber", ColumnSize.UInt16), new ColumnInfo(4, "Flags", ColumnSize.UInt32), new ColumnInfo(5, "PublicKeyOrToken", ColumnSize.Blob), new ColumnInfo(6, "Name", ColumnSize.Strings), new ColumnInfo(7, "Locale", ColumnSize.Strings), new ColumnInfo(8, "HashValue", ColumnSize.Blob), }); tableInfos[(int)Table.AssemblyRefProcessor] = new TableInfo(Table.AssemblyRefProcessor, "AssemblyRefProcessor", new ColumnInfo[] { new ColumnInfo(0, "Processor", ColumnSize.UInt32), new ColumnInfo(1, "AssemblyRef", ColumnSize.AssemblyRef), }); tableInfos[(int)Table.AssemblyRefOS] = new TableInfo(Table.AssemblyRefOS, "AssemblyRefOS", new ColumnInfo[] { new ColumnInfo(0, "OSPlatformId", ColumnSize.UInt32), new ColumnInfo(1, "OSMajorVersion", ColumnSize.UInt32), new ColumnInfo(2, "OSMinorVersion", ColumnSize.UInt32), new ColumnInfo(3, "AssemblyRef", ColumnSize.AssemblyRef), }); tableInfos[(int)Table.File] = new TableInfo(Table.File, "File", new ColumnInfo[] { new ColumnInfo(0, "Flags", ColumnSize.UInt32), new ColumnInfo(1, "Name", ColumnSize.Strings), new ColumnInfo(2, "HashValue", ColumnSize.Blob), }); tableInfos[(int)Table.ExportedType] = new TableInfo(Table.ExportedType, "ExportedType", new ColumnInfo[] { new ColumnInfo(0, "Flags", ColumnSize.UInt32), new ColumnInfo(1, "TypeDefId", ColumnSize.UInt32), new ColumnInfo(2, "TypeName", ColumnSize.Strings), new ColumnInfo(3, "TypeNamespace", ColumnSize.Strings), new ColumnInfo(4, "Implementation", ColumnSize.Implementation), }); tableInfos[(int)Table.ManifestResource] = new TableInfo(Table.ManifestResource, "ManifestResource", new ColumnInfo[] { new ColumnInfo(0, "Offset", ColumnSize.UInt32), new ColumnInfo(1, "Flags", ColumnSize.UInt32), new ColumnInfo(2, "Name", ColumnSize.Strings), new ColumnInfo(3, "Implementation", ColumnSize.Implementation), }); tableInfos[(int)Table.NestedClass] = new TableInfo(Table.NestedClass, "NestedClass", new ColumnInfo[] { new ColumnInfo(0, "NestedClass", ColumnSize.TypeDef), new ColumnInfo(1, "EnclosingClass", ColumnSize.TypeDef), }); if (majorVersion == 1 && minorVersion == 1) { tableInfos[(int)Table.GenericParam] = new TableInfo(Table.GenericParam, "GenericParam", new ColumnInfo[] { new ColumnInfo(0, "Number", ColumnSize.UInt16), new ColumnInfo(1, "Flags", ColumnSize.UInt16), new ColumnInfo(2, "Owner", ColumnSize.TypeOrMethodDef), new ColumnInfo(3, "Name", ColumnSize.Strings), new ColumnInfo(4, "Kind", ColumnSize.TypeDefOrRef), }); } else { tableInfos[(int)Table.GenericParam] = new TableInfo(Table.GenericParam, "GenericParam", new ColumnInfo[] { new ColumnInfo(0, "Number", ColumnSize.UInt16), new ColumnInfo(1, "Flags", ColumnSize.UInt16), new ColumnInfo(2, "Owner", ColumnSize.TypeOrMethodDef), new ColumnInfo(3, "Name", ColumnSize.Strings), }); } tableInfos[(int)Table.MethodSpec] = new TableInfo(Table.MethodSpec, "MethodSpec", new ColumnInfo[] { new ColumnInfo(0, "Method", ColumnSize.MethodDefOrRef), new ColumnInfo(1, "Instantiation", ColumnSize.Blob), }); tableInfos[(int)Table.GenericParamConstraint] = new TableInfo(Table.GenericParamConstraint, "GenericParamConstraint", new ColumnInfo[] { new ColumnInfo(0, "Owner", ColumnSize.GenericParam), new ColumnInfo(1, "Constraint", ColumnSize.TypeDefOrRef), }); tableInfos[0x2D] = new TableInfo((Table)0x2D, string.Empty, new ColumnInfo[] { }); tableInfos[0x2E] = new TableInfo((Table)0x2E, string.Empty, new ColumnInfo[] { }); tableInfos[0x2F] = new TableInfo((Table)0x2F, string.Empty, new ColumnInfo[] { }); tableInfos[(int)Table.Document] = new TableInfo(Table.Document, "Document", new ColumnInfo[] { new ColumnInfo(0, "Name", ColumnSize.Blob), new ColumnInfo(1, "HashAlgorithm", ColumnSize.GUID), new ColumnInfo(2, "Hash", ColumnSize.Blob), new ColumnInfo(3, "Language", ColumnSize.GUID), }); tableInfos[(int)Table.MethodDebugInformation] = new TableInfo(Table.MethodDebugInformation, "MethodDebugInformation", new ColumnInfo[] { new ColumnInfo(0, "Document", ColumnSize.Document), new ColumnInfo(1, "SequencePoints", ColumnSize.Blob), }); tableInfos[(int)Table.LocalScope] = new TableInfo(Table.LocalScope, "LocalScope", new ColumnInfo[] { new ColumnInfo(0, "Method", ColumnSize.Method), new ColumnInfo(1, "ImportScope", ColumnSize.ImportScope), new ColumnInfo(2, "VariableList", ColumnSize.LocalVariable), new ColumnInfo(3, "ConstantList", ColumnSize.LocalConstant), new ColumnInfo(4, "StartOffset", ColumnSize.UInt32), new ColumnInfo(5, "Length", ColumnSize.UInt32), }); tableInfos[(int)Table.LocalVariable] = new TableInfo(Table.LocalVariable, "LocalVariable", new ColumnInfo[] { new ColumnInfo(0, "Attributes", ColumnSize.UInt16), new ColumnInfo(1, "Index", ColumnSize.UInt16), new ColumnInfo(2, "Name", ColumnSize.Strings), }); tableInfos[(int)Table.LocalConstant] = new TableInfo(Table.LocalConstant, "LocalConstant", new ColumnInfo[] { new ColumnInfo(0, "Name", ColumnSize.Strings), new ColumnInfo(1, "Signature", ColumnSize.Blob), }); tableInfos[(int)Table.ImportScope] = new TableInfo(Table.ImportScope, "ImportScope", new ColumnInfo[] { new ColumnInfo(0, "Parent", ColumnSize.ImportScope), new ColumnInfo(1, "Imports", ColumnSize.Blob), }); tableInfos[(int)Table.StateMachineMethod] = new TableInfo(Table.StateMachineMethod, "StateMachineMethod", new ColumnInfo[] { new ColumnInfo(0, "MoveNextMethod", ColumnSize.Method), new ColumnInfo(1, "KickoffMethod", ColumnSize.Method), }); tableInfos[(int)Table.CustomDebugInformation] = new TableInfo(Table.CustomDebugInformation, "CustomDebugInformation", new ColumnInfo[] { new ColumnInfo(0, "Parent", ColumnSize.HasCustomDebugInformation), new ColumnInfo(1, "Kind", ColumnSize.GUID), new ColumnInfo(2, "Value", ColumnSize.Blob), }); return this.tableInfos = tableInfos; } } } dnlib-2.1_VS2010/src/DotNet/MD/ENCMetaData.cs000066400000000000000000000370601325033663500202140ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using dnlib.IO; using dnlib.PE; using dnlib.Threading; namespace dnlib.DotNet.MD { /// /// Used when a #- stream is present in the metadata /// sealed class ENCMetaData : MetaData { static readonly UTF8String DeletedName = "_Deleted"; bool hasMethodPtr, hasFieldPtr, hasParamPtr, hasEventPtr, hasPropertyPtr; bool hasDeletedRows; readonly Dictionary sortedTables = new Dictionary(); #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// public override bool IsCompressed { get { return false; } } /// public ENCMetaData(IPEImage peImage, ImageCor20Header cor20Header, MetaDataHeader mdHeader) : base(peImage, cor20Header, mdHeader) { } /// internal ENCMetaData(MetaDataHeader mdHeader, bool isStandalonePortablePdb) : base(mdHeader, isStandalonePortablePdb) { } /// protected override void InitializeInternal(IImageStream mdStream) { bool disposeOfMdStream = false; IImageStream imageStream = null; DotNetStream dns = null; try { if (peImage != null) { Debug.Assert(mdStream == null); Debug.Assert(cor20Header != null); var mdOffset = peImage.ToFileOffset(cor20Header.MetaData.VirtualAddress); mdStream = peImage.CreateStream(mdOffset, cor20Header.MetaData.Size); disposeOfMdStream = true; } else Debug.Assert(mdStream != null); foreach (var sh in mdHeader.StreamHeaders) { imageStream = mdStream.Create((FileOffset)sh.Offset, sh.StreamSize); switch (sh.Name.ToUpperInvariant()) { case "#STRINGS": if (stringsStream == null) { stringsStream = new StringsStream(imageStream, sh); imageStream = null; allStreams.Add(stringsStream); continue; } break; case "#US": if (usStream == null) { usStream = new USStream(imageStream, sh); imageStream = null; allStreams.Add(usStream); continue; } break; case "#BLOB": if (blobStream == null) { blobStream = new BlobStream(imageStream, sh); imageStream = null; allStreams.Add(blobStream); continue; } break; case "#GUID": if (guidStream == null) { guidStream = new GuidStream(imageStream, sh); imageStream = null; allStreams.Add(guidStream); continue; } break; case "#~": // Only if #Schema is used case "#-": if (tablesStream == null) { tablesStream = new TablesStream(imageStream, sh); imageStream = null; allStreams.Add(tablesStream); continue; } break; case "#PDB": // Case sensitive comparison since it's a stream that's not read by the CLR, // only by other libraries eg. System.Reflection.Metadata. if (isStandalonePortablePdb && pdbStream == null && sh.Name == "#Pdb") { pdbStream = new PdbStream(imageStream, sh); imageStream = null; allStreams.Add(pdbStream); continue; } break; } dns = new DotNetStream(imageStream, sh); imageStream = null; allStreams.Add(dns); dns = null; } } finally { if (disposeOfMdStream) mdStream.Dispose(); if (imageStream != null) imageStream.Dispose(); if (dns != null) dns.Dispose(); } if (tablesStream == null) throw new BadImageFormatException("Missing MD stream"); if (pdbStream != null) tablesStream.Initialize(pdbStream.TypeSystemTableRows); else tablesStream.Initialize(null); // The pointer tables are used iff row count != 0 hasFieldPtr = !tablesStream.FieldPtrTable.IsEmpty; hasMethodPtr = !tablesStream.MethodPtrTable.IsEmpty; hasParamPtr = !tablesStream.ParamPtrTable.IsEmpty; hasEventPtr = !tablesStream.EventPtrTable.IsEmpty; hasPropertyPtr = !tablesStream.PropertyPtrTable.IsEmpty; hasDeletedRows = tablesStream.HasDelete; } /// public override RidList GetTypeDefRidList() { if (!hasDeletedRows) return base.GetTypeDefRidList(); uint rows = tablesStream.TypeDefTable.Rows; var list = new RandomRidList((int)rows); for (uint rid = 1; rid <= rows; rid++) { var row = tablesStream.ReadTypeDefRow(rid); if (row == null) continue; // Should never happen since rid is valid // RTSpecialName is ignored by the CLR. It's only the name that indicates // whether it's been deleted. if (stringsStream.ReadNoNull(row.Name).StartsWith(DeletedName)) continue; // ignore this deleted row list.Add(rid); } return list; } /// public override RidList GetExportedTypeRidList() { if (!hasDeletedRows) return base.GetExportedTypeRidList(); uint rows = tablesStream.ExportedTypeTable.Rows; var list = new RandomRidList((int)rows); for (uint rid = 1; rid <= rows; rid++) { var row = tablesStream.ReadExportedTypeRow(rid); if (row == null) continue; // Should never happen since rid is valid // RTSpecialName is ignored by the CLR. It's only the name that indicates // whether it's been deleted. if (stringsStream.ReadNoNull(row.TypeName).StartsWith(DeletedName)) continue; // ignore this deleted row list.Add(rid); } return list; } /// /// Converts a logical Field rid to a physical Field rid /// /// A valid rid /// Converted rid or any invalid rid value if is invalid uint ToFieldRid(uint listRid) { if (!hasFieldPtr) return listRid; uint listValue; return tablesStream.ReadColumn(tablesStream.FieldPtrTable, listRid, 0, out listValue) ? listValue : 0; } /// /// Converts a logical Method rid to a physical Method rid /// /// A valid rid /// Converted rid or any invalid rid value if is invalid uint ToMethodRid(uint listRid) { if (!hasMethodPtr) return listRid; uint listValue; return tablesStream.ReadColumn(tablesStream.MethodPtrTable, listRid, 0, out listValue) ? listValue : 0; } /// /// Converts a logical Param rid to a physical Param rid /// /// A valid rid /// Converted rid or any invalid rid value if is invalid uint ToParamRid(uint listRid) { if (!hasParamPtr) return listRid; uint listValue; return tablesStream.ReadColumn(tablesStream.ParamPtrTable, listRid, 0, out listValue) ? listValue : 0; } /// /// Converts a logical Event rid to a physical Event rid /// /// A valid rid /// Converted rid or any invalid rid value if is invalid uint ToEventRid(uint listRid) { if (!hasEventPtr) return listRid; uint listValue; return tablesStream.ReadColumn(tablesStream.EventPtrTable, listRid, 0, out listValue) ? listValue : 0; } /// /// Converts a logical Property rid to a physical Property rid /// /// A valid rid /// Converted rid or any invalid rid value if is invalid uint ToPropertyRid(uint listRid) { if (!hasPropertyPtr) return listRid; uint listValue; return tablesStream.ReadColumn(tablesStream.PropertyPtrTable, listRid, 0, out listValue) ? listValue : 0; } /// public override RidList GetFieldRidList(uint typeDefRid) { var list = GetRidList(tablesStream.TypeDefTable, typeDefRid, 4, tablesStream.FieldTable); if (list.Length == 0 || (!hasFieldPtr && !hasDeletedRows)) return list; var destTable = tablesStream.FieldTable; var newList = new RandomRidList((int)list.Length); for (uint i = 0; i < list.Length; i++) { var rid = ToFieldRid(list[i]); if (destTable.IsInvalidRID(rid)) continue; if (hasDeletedRows) { // It's a deleted row if RTSpecialName is set and name is "_Deleted" var row = tablesStream.ReadFieldRow(rid); if (row == null) continue; // Should never happen since rid is valid if ((row.Flags & (uint)FieldAttributes.RTSpecialName) != 0) { if (stringsStream.ReadNoNull(row.Name).StartsWith(DeletedName)) continue; // ignore this deleted row } } // It's a valid non-deleted rid so add it newList.Add(rid); } return newList; } /// public override RidList GetMethodRidList(uint typeDefRid) { var list = GetRidList(tablesStream.TypeDefTable, typeDefRid, 5, tablesStream.MethodTable); if (list.Length == 0 || (!hasMethodPtr && !hasDeletedRows)) return list; var destTable = tablesStream.MethodTable; var newList = new RandomRidList((int)list.Length); for (uint i = 0; i < list.Length; i++) { var rid = ToMethodRid(list[i]); if (destTable.IsInvalidRID(rid)) continue; if (hasDeletedRows) { // It's a deleted row if RTSpecialName is set and name is "_Deleted" var row = tablesStream.ReadMethodRow(rid); if (row == null) continue; // Should never happen since rid is valid if ((row.Flags & (uint)MethodAttributes.RTSpecialName) != 0) { if (stringsStream.ReadNoNull(row.Name).StartsWith(DeletedName)) continue; // ignore this deleted row } } // It's a valid non-deleted rid so add it newList.Add(rid); } return newList; } /// public override RidList GetParamRidList(uint methodRid) { var list = GetRidList(tablesStream.MethodTable, methodRid, 5, tablesStream.ParamTable); if (list.Length == 0 || !hasParamPtr) return list; var destTable = tablesStream.ParamTable; var newList = new RandomRidList((int)list.Length); for (uint i = 0; i < list.Length; i++) { var rid = ToParamRid(list[i]); if (destTable.IsInvalidRID(rid)) continue; newList.Add(rid); } return newList; } /// public override RidList GetEventRidList(uint eventMapRid) { var list = GetRidList(tablesStream.EventMapTable, eventMapRid, 1, tablesStream.EventTable); if (list.Length == 0 || (!hasEventPtr && !hasDeletedRows)) return list; var destTable = tablesStream.EventTable; var newList = new RandomRidList((int)list.Length); for (uint i = 0; i < list.Length; i++) { var rid = ToEventRid(list[i]); if (destTable.IsInvalidRID(rid)) continue; if (hasDeletedRows) { // It's a deleted row if RTSpecialName is set and name is "_Deleted" var row = tablesStream.ReadEventRow(rid); if (row == null) continue; // Should never happen since rid is valid if ((row.EventFlags & (uint)EventAttributes.RTSpecialName) != 0) { if (stringsStream.ReadNoNull(row.Name).StartsWith(DeletedName)) continue; // ignore this deleted row } } // It's a valid non-deleted rid so add it newList.Add(rid); } return newList; } /// public override RidList GetPropertyRidList(uint propertyMapRid) { var list = GetRidList(tablesStream.PropertyMapTable, propertyMapRid, 1, tablesStream.PropertyTable); if (list.Length == 0 || (!hasPropertyPtr && !hasDeletedRows)) return list; var destTable = tablesStream.PropertyTable; var newList = new RandomRidList((int)list.Length); for (uint i = 0; i < list.Length; i++) { var rid = ToPropertyRid(list[i]); if (destTable.IsInvalidRID(rid)) continue; if (hasDeletedRows) { // It's a deleted row if RTSpecialName is set and name is "_Deleted" var row = tablesStream.ReadPropertyRow(rid); if (row == null) continue; // Should never happen since rid is valid if ((row.PropFlags & (uint)PropertyAttributes.RTSpecialName) != 0) { if (stringsStream.ReadNoNull(row.Name).StartsWith(DeletedName)) continue; // ignore this deleted row } } // It's a valid non-deleted rid so add it newList.Add(rid); } return newList; } /// /// Gets a rid list (eg. field list) /// /// Source table, eg. TypeDef /// Row ID in /// Column index in , eg. 4 for TypeDef.FieldList /// Destination table, eg. Field /// A new instance RidList GetRidList(MDTable tableSource, uint tableSourceRid, int colIndex, MDTable tableDest) { var column = tableSource.TableInfo.Columns[colIndex]; uint startRid, nextListRid; bool hasNext; #if THREAD_SAFE tablesStream.theLock.EnterWriteLock(); try { #endif if (!tablesStream.ReadColumn_NoLock(tableSource, tableSourceRid, column, out startRid)) return RidList.Empty; hasNext = tablesStream.ReadColumn_NoLock(tableSource, tableSourceRid + 1, column, out nextListRid); #if THREAD_SAFE } finally { tablesStream.theLock.ExitWriteLock(); } #endif uint lastRid = tableDest.Rows + 1; if (startRid == 0 || startRid >= lastRid) return RidList.Empty; uint endRid = hasNext && nextListRid != 0 ? nextListRid : lastRid; if (endRid < startRid) endRid = startRid; if (endRid > lastRid) endRid = lastRid; return new ContiguousRidList(startRid, endRid - startRid); } /// protected override uint BinarySearch_NoLock(MDTable tableSource, int keyColIndex, uint key) { var keyColumn = tableSource.TableInfo.Columns[keyColIndex]; uint ridLo = 1, ridHi = tableSource.Rows; while (ridLo <= ridHi) { uint rid = (ridLo + ridHi) / 2; uint key2; if (!tablesStream.ReadColumn_NoLock(tableSource, rid, keyColumn, out key2)) break; // Never happens since rid is valid if (key == key2) return rid; if (key2 > key) ridHi = rid - 1; else ridLo = rid + 1; } if (tableSource.Table == Table.GenericParam && !tablesStream.IsSorted(tableSource)) return LinearSearch_NoLock(tableSource, keyColIndex, key); return 0; } /// /// Linear searches the table (O(n)) for a rid whose key column at index /// is equal to . /// /// Table to search /// Key column index /// Key /// The rid of the found row, or 0 if none found uint LinearSearch_NoLock(MDTable tableSource, int keyColIndex, uint key) { if (tableSource == null) return 0; var keyColumn = tableSource.TableInfo.Columns[keyColIndex]; for (uint rid = 1; rid <= tableSource.Rows; rid++) { uint key2; if (!tablesStream.ReadColumn_NoLock(tableSource, rid, keyColumn, out key2)) break; // Never happens since rid is valid if (key == key2) return rid; } return 0; } /// protected override RidList FindAllRowsUnsorted(MDTable tableSource, int keyColIndex, uint key) { if (tablesStream.IsSorted(tableSource)) return FindAllRows(tableSource, keyColIndex, key); SortedTable sortedTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (!sortedTables.TryGetValue(tableSource.Table, out sortedTable)) sortedTables[tableSource.Table] = sortedTable = new SortedTable(tableSource, keyColIndex); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif return sortedTable.FindAllRows(key); } } } dnlib-2.1_VS2010/src/DotNet/MD/GuidStream.cs000066400000000000000000000021241325033663500202430ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; namespace dnlib.DotNet.MD { /// /// Represents the #GUID stream /// public sealed class GuidStream : HeapStream { /// public GuidStream() { } /// public GuidStream(IImageStream imageStream, StreamHeader streamHeader) : base(imageStream, streamHeader) { } /// public override bool IsValidIndex(uint index) { return index == 0 || (index <= 0x10000000 && IsValidOffset((index - 1) * 16, 16)); } /// /// Read a /// /// Index into this stream /// A or null if is 0 or invalid public Guid? Read(uint index) { if (index == 0 || !IsValidIndex(index)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock((index - 1) * 16); return new Guid(reader.ReadBytes(16)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } } dnlib-2.1_VS2010/src/DotNet/MD/HeapType.cs000066400000000000000000000006171325033663500177230ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.MD { /// /// Heap type. The values are set in stone by MS. Don't change. /// public enum HeapType : uint { /// #Strings heap Strings = 0, /// #GUID heap Guid = 1, /// #Blob heap Blob = 2, /// #US heap US = 3, } } dnlib-2.1_VS2010/src/DotNet/MD/HotHeapStream.cs000066400000000000000000000150421325033663500207060ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using System.Runtime.ExceptionServices; using System.Security; using dnlib.IO; namespace dnlib.DotNet.MD { /// /// Stores some/all heap data /// abstract class HotHeapStream : IDisposable { readonly HeapType heapType; protected readonly IImageStream reader; protected readonly long baseOffset; protected bool invalid; protected long posData; protected long posIndexes; protected long posRids; protected uint numRids; protected long offsetMask; /// /// Gets the heap type /// public HeapType HeapType { get { return heapType; } } /// /// Constructor /// /// Heap type /// Data stream /// Offset in of start of data protected HotHeapStream(HeapType heapType, IImageStream reader, long baseOffset) { this.heapType = heapType; this.reader = reader; this.baseOffset = baseOffset; } /// /// Must be called once after creating it so it can initialize /// /// Offset mask (0xFFFFFFFF or 0xFFFFFFFFFFFFFFFF) public abstract void Initialize(long mask); /// /// Returns a stream that can access a blob /// /// Offset in the original heap. If it's the #GUID heap, it should /// be (index - 1) * 16 /// The reader (owned by us) or null if the data isn't present public IImageStream GetBlobReader(uint originalHeapOffset) { long dataOffset; if (GetBlobOffset(originalHeapOffset, out dataOffset)) { reader.Position = dataOffset; return reader; } return null; } /// /// Returns the offset in of some data /// /// Original heap offset /// Updated with offset in of data /// true if data is present, false if data is not present protected abstract bool GetBlobOffset(uint originalHeapOffset, out long dataOffset); /// /// Binary searches the rids table for /// /// Original heap offset /// The rids table index or if not found protected uint BinarySearch(uint originalHeapOffset) { uint lo = 0, hi = numRids - 1; while (lo <= hi && hi != uint.MaxValue) { uint index = (lo + hi) / 2; uint val = reader.ReadUInt32At(posRids + index * 4); if (originalHeapOffset == val) return index; if (originalHeapOffset > val) lo = index + 1; else hi = index - 1; } return uint.MaxValue; } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose method /// /// true if called by protected virtual void Dispose(bool disposing) { if (disposing) { if (reader != null) reader.Dispose(); } } } /// /// Hot heap stream (CLR 2.0) /// sealed class HotHeapStreamCLR20 : HotHeapStream { /// /// Constructor /// /// Heap type /// Data stream /// Offset in of start of data public HotHeapStreamCLR20(HeapType heapType, IImageStream reader, long baseOffset) : base(heapType, reader, baseOffset) { } /// [HandleProcessCorruptedStateExceptions, SecurityCritical] // Req'd on .NET 4.0 public override void Initialize(long mask) { try { offsetMask = mask; reader.Position = baseOffset; posData = (baseOffset - reader.ReadInt32()) & mask; posIndexes = (baseOffset - (reader.ReadInt32() & ~3)) & mask; uint ridsOffset = reader.ReadUInt32(); numRids = ridsOffset / 4; posRids = (baseOffset - numRids * 4) & mask; } // Ignore exceptions. The CLR only reads these values when needed. Assume // that this was invalid data that the CLR will never read anyway. catch (AccessViolationException) { invalid = true; } catch (IOException) { invalid = true; } } /// protected override bool GetBlobOffset(uint originalHeapOffset, out long dataOffset) { if (invalid) { dataOffset = 0; return false; } uint index = BinarySearch(originalHeapOffset); if (index == uint.MaxValue) { dataOffset = 0; return false; } if (index == 0) dataOffset = posData; else dataOffset = posData + reader.ReadUInt32At((posIndexes + (index - 1) * 4) & offsetMask); dataOffset &= offsetMask; return true; } } /// /// Hot heap stream (CLR 4.0) /// sealed class HotHeapStreamCLR40 : HotHeapStream { /// /// Constructor /// /// Heap type /// Data stream /// Offset in of start of data public HotHeapStreamCLR40(HeapType heapType, IImageStream reader, long baseOffset) : base(heapType, reader, baseOffset) { } /// [HandleProcessCorruptedStateExceptions, SecurityCritical] // Req'd on .NET 4.0 public override void Initialize(long mask) { try { offsetMask = mask; reader.Position = baseOffset; uint ridsOffset = reader.ReadUInt32(); numRids = ridsOffset / 4; posRids = (baseOffset - ridsOffset) & mask; posIndexes = (baseOffset - reader.ReadInt32()) & mask; posData = (baseOffset - reader.ReadInt32()) & mask; } // Ignore exceptions. The CLR only reads these values when needed. Assume // that this was invalid data that the CLR will never read anyway. catch (AccessViolationException) { invalid = true; } catch (IOException) { invalid = true; } } /// protected override bool GetBlobOffset(uint originalHeapOffset, out long dataOffset) { if (invalid) { dataOffset = 0; return false; } uint index = BinarySearch(originalHeapOffset); if (index == uint.MaxValue) { dataOffset = 0; return false; } dataOffset = posData + reader.ReadUInt32At((posIndexes + index * 4) & offsetMask); dataOffset &= offsetMask; return true; } } } dnlib-2.1_VS2010/src/DotNet/MD/HotHeapVersion.cs000066400000000000000000000004631325033663500211010ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.MD { /// /// Hot heap version /// public enum HotHeapVersion { /// /// CLR 2.0 (.NET 2.0 - 3.5) /// CLR20, /// /// CLR 4.0 (.NET 4.0 - 4.5) /// CLR40, } } dnlib-2.1_VS2010/src/DotNet/MD/HotStream.cs000066400000000000000000000236141325033663500201140ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using System.Runtime.ExceptionServices; using System.Security; using System.Threading; using dnlib.IO; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet.MD { /// /// Represents the (undocumented) #! stream. The CLR only uses this stream if the /// normal compressed tables stream (#~) is used. /// abstract class HotStream : DotNetStream { protected readonly IImageStream fullStream; protected readonly long baseOffset; protected readonly long endOffset; protected HotTableStream hotTableStream; protected ThreadSafe.IList hotHeapStreams; /// /// Gets the or null if there's none /// public HotTableStream HotTableStream { get { if (hotTableStream == null) { var newHts = CreateHotTableStream(); if (Interlocked.CompareExchange(ref hotTableStream, newHts, null) != null) newHts.Dispose(); } return hotTableStream; } } /// /// Gets all s /// public IList HotHeapStreams { get { if (hotHeapStreams == null) { var newHhs = CreateHotHeapStreams(); if (Interlocked.CompareExchange(ref hotHeapStreams, newHhs, null) != null) { foreach (var hhs in newHhs) hhs.Dispose(); } } return hotHeapStreams; } } /// /// Creates a instance /// /// Hot heap version /// Heap stream /// Stream header info /// Stream for the full PE file /// Offset in where the data starts /// A instance or null if /// is invalid public static HotStream Create(HotHeapVersion version, IImageStream imageStream, StreamHeader streamHeader, IImageStream fullStream, FileOffset baseOffset) { switch (version) { case HotHeapVersion.CLR20: return new HotStreamCLR20(imageStream, streamHeader, fullStream, baseOffset); case HotHeapVersion.CLR40: return new HotStreamCLR40(imageStream, streamHeader, fullStream, baseOffset); default: return null; } } /// /// Constructor /// /// Heap stream /// Stream header info /// Stream for the full PE file /// Offset in where the data starts protected HotStream(IImageStream imageStream, StreamHeader streamHeader, IImageStream fullStream, FileOffset baseOffset) : base(imageStream, streamHeader) { this.fullStream = fullStream; this.baseOffset = (long)baseOffset; this.endOffset = (long)baseOffset + imageStream.Length; } [HandleProcessCorruptedStateExceptions, SecurityCritical] // Req'd on .NET 4.0 HotTableStream CreateHotTableStream() { try { return CreateHotTableStreamImpl(); } catch (AccessViolationException) { return null; } catch (IOException) { return null; } } [HandleProcessCorruptedStateExceptions, SecurityCritical] // Req'd on .NET 4.0 ThreadSafe.IList CreateHotHeapStreams() { try { return CreateHotHeapStreams2(); } catch (AccessViolationException) { return null; } catch (IOException) { return null; } } ThreadSafe.IList CreateHotHeapStreams2() { var list = ThreadSafeListCreator.Create(); try { long dirBaseOffs = GetHotHeapDirectoryBaseOffset(); for (long offs = dirBaseOffs; offs + 8 <= endOffset - 8; offs += 8) { fullStream.Position = offs; HeapType heapType; long hotHeapOffset; ReadHotHeapDirectory(fullStream, dirBaseOffs, out heapType, out hotHeapOffset); IImageStream dataStream = null; HotHeapStream hotHeapStream = null; try { dataStream = fullStream.Clone(); list.Add(hotHeapStream = CreateHotHeapStream(heapType, dataStream, hotHeapOffset)); dataStream = null; hotHeapStream = null; } catch { if (hotHeapStream != null) hotHeapStream.Dispose(); if (dataStream != null) dataStream.Dispose(); throw; } } } catch { foreach (var h in list) h.Dispose(); throw; } return list; } /// /// Reads a hot heap directory /// /// Reader stream /// Pool directory base offset /// Updated with heap type /// Updated with heap offset protected abstract void ReadHotHeapDirectory(IImageStream reader, long dirBaseOffs, out HeapType heapType, out long hotHeapOffs); /// /// Creates a /// /// Heap type /// Data stream /// Offset in of start of data /// A new instance protected abstract HotHeapStream CreateHotHeapStream(HeapType heapType, IImageStream stream, long baseOffset); /// /// Creates the /// /// A new instance or null if it doesn't exist protected abstract HotTableStream CreateHotTableStreamImpl(); /// /// Gets the offset of the hot table directory in /// protected long GetHotTableBaseOffset() { // All bits in this dword are used return endOffset - 8 - HotTableStream.HOT_HEAP_DIR_SIZE - fullStream.ReadUInt32At(endOffset - 8); } /// /// Gets the offset of the hot pool directory in /// protected abstract long GetHotHeapDirectoryBaseOffset(); /// protected override void Dispose(bool disposing) { if (disposing) { IDisposable id = fullStream; if (id != null) id.Dispose(); id = hotTableStream; if (id != null) id.Dispose(); var hhs = hotHeapStreams; if (hhs != null) { foreach (var hs in hhs) { if (hs != null) hs.Dispose(); } } } base.Dispose(disposing); } } /// /// Represents the #! stream. Should be used if the module uses CLR 2.0 (.NET 2.0 - 3.5) /// sealed class HotStreamCLR20 : HotStream { /// /// Constructor /// /// Heap stream /// Stream header info /// Stream for the full PE file /// Offset in where the data starts public HotStreamCLR20(IImageStream imageStream, StreamHeader streamHeader, IImageStream fullStream, FileOffset baseOffset) : base(imageStream, streamHeader, fullStream, baseOffset) { } /// protected override HotTableStream CreateHotTableStreamImpl() { IImageStream stream = null; try { stream = fullStream.Clone(); return new HotTableStreamCLR20(stream, GetHotTableBaseOffset()); } catch { if (stream != null) stream.Dispose(); throw; } } /// protected override long GetHotHeapDirectoryBaseOffset() { // Lower 2 bits are ignored return endOffset - 8 - (fullStream.ReadUInt32At(endOffset - 8 + 4) & ~3); } /// protected override void ReadHotHeapDirectory(IImageStream reader, long dirBaseOffs, out HeapType heapType, out long hotHeapOffs) { heapType = (HeapType)reader.ReadUInt32(); // Lower 2 bits are ignored hotHeapOffs = dirBaseOffs - (reader.ReadUInt32() & ~3); } /// protected override HotHeapStream CreateHotHeapStream(HeapType heapType, IImageStream stream, long baseOffset) { return new HotHeapStreamCLR20(heapType, stream, baseOffset); } } /// /// Represents the #! stream. Should be used if the module uses CLR 4.0 (.NET 4.0 - 4.5) /// sealed class HotStreamCLR40 : HotStream { /// /// Constructor /// /// Heap stream /// Stream header info /// Stream for the full PE file /// Offset in where the data starts public HotStreamCLR40(IImageStream imageStream, StreamHeader streamHeader, IImageStream fullStream, FileOffset baseOffset) : base(imageStream, streamHeader, fullStream, baseOffset) { } /// protected override HotTableStream CreateHotTableStreamImpl() { IImageStream stream = null; try { stream = fullStream.Clone(); return new HotTableStreamCLR40(stream, GetHotTableBaseOffset()); } catch { if (stream != null) stream.Dispose(); throw; } } /// protected override long GetHotHeapDirectoryBaseOffset() { // All bits are used return endOffset - 8 - fullStream.ReadUInt32At(endOffset - 8 + 4); } /// protected override void ReadHotHeapDirectory(IImageStream reader, long dirBaseOffs, out HeapType heapType, out long hotHeapOffs) { heapType = (HeapType)reader.ReadUInt32(); // All bits are used hotHeapOffs = dirBaseOffs - reader.ReadUInt32(); } /// protected override HotHeapStream CreateHotHeapStream(HeapType heapType, IImageStream stream, long baseOffset) { return new HotHeapStreamCLR40(heapType, stream, baseOffset); } } } dnlib-2.1_VS2010/src/DotNet/MD/HotTableStream.cs000066400000000000000000000206561325033663500210670ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using System.Runtime.ExceptionServices; using System.Security; using dnlib.IO; namespace dnlib.DotNet.MD { /// /// Stores some/all rows of a table /// abstract class HotTableStream : IDisposable { protected const int MAX_TABLES = (int)Table.GenericParamConstraint + 1; internal const uint HOT_HEAP_DIR_SIZE = 4 + MAX_TABLES * 4; protected readonly IImageStream fullStream; protected readonly long baseOffset; /// /// Constructor /// /// Data stream /// Offset in of start of the /// hot table directory header protected HotTableStream(IImageStream fullStream, long baseOffset) { this.fullStream = fullStream; this.baseOffset = baseOffset; } /// /// Must be called once after creating it so it can initialize /// /// Offset mask (0xFFFFFFFF or 0xFFFFFFFFFFFFFFFF) public abstract void Initialize(long mask); /// /// Returns a reader positioned at a table row /// /// Table /// A valid row ID (i.e., >= 1 and <= number of rows) /// The reader (owned by us) or null if the row isn't present public IImageStream GetTableReader(MDTable table, uint rid) { long offset; if (GetRowOffset(table, rid, out offset)) { fullStream.Position = offset; return fullStream; } return null; } /// /// Returns the offset (in ) of a row /// /// Table /// A valid row ID (i.e., >= 1 and <= number of rows) /// Updated with the offset /// true if the row exists, false if the row doesn't exist protected abstract bool GetRowOffset(MDTable table, uint rid, out long offset); /// /// Add offsets /// /// Mask /// Base offset /// Displacement /// Returns 0 if is 0, else returns /// the sum of and masked /// by protected static long AddOffsets(long mask, long baseOffset, long displ) { if (displ == 0) return 0; return (baseOffset + displ) & mask; } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose method /// /// true if called by protected virtual void Dispose(bool disposing) { if (disposing) { var fs = fullStream; if (fs != null) fs.Dispose(); } } } /// /// Hot table stream (CLR 2.0) /// sealed class HotTableStreamCLR20 : HotTableStream { TableHeader[] tableHeaders; class TableHeader { public uint numRows; public long posTable1; public long posTable2; public long posData; public int shift; public uint mask; } /// /// Constructor /// /// Data stream /// Offset in of start of the /// hot table directory header public HotTableStreamCLR20(IImageStream fullStream, long baseOffset) : base(fullStream, baseOffset) { } /// [HandleProcessCorruptedStateExceptions, SecurityCritical] // Req'd on .NET 4.0 public override void Initialize(long mask) { tableHeaders = new TableHeader[MAX_TABLES]; for (int i = 0; i < tableHeaders.Length; i++) { fullStream.Position = baseOffset + 4 + i * 4; int headerOffs = fullStream.ReadInt32(); if (headerOffs == 0) continue; var headerBaseOffs = (baseOffset + headerOffs) & mask; fullStream.Position = headerBaseOffs; try { var header = new TableHeader { numRows = fullStream.ReadUInt32(), posTable1 = AddOffsets(mask, headerBaseOffs, fullStream.ReadInt32()), posTable2 = (headerBaseOffs + fullStream.ReadInt32()) & mask, posData = (headerBaseOffs + fullStream.ReadInt32()) & mask, shift = fullStream.ReadUInt16(), }; header.mask = (1U << header.shift) - 1; tableHeaders[i] = header; } // Ignore exceptions. The CLR only reads these values when needed. Assume // that this was invalid data that the CLR will never read anyway. catch (AccessViolationException) { } catch (IOException) { } } } /// protected override bool GetRowOffset(MDTable table, uint rid, out long offset) { offset = 0; if ((uint)table.Table >= (uint)tableHeaders.Length) return false; var header = tableHeaders[(int)table.Table]; if (header == null) return false; // Check whether the whole table is in memory if (header.posTable1 == 0) { offset = header.posData + (rid - 1) * table.RowSize; return true; } fullStream.Position = header.posTable1 + (rid & header.mask) * 2; int index = fullStream.ReadUInt16(); int stop = fullStream.ReadUInt16(); fullStream.Position = header.posTable2 + index; byte highBits = (byte)(rid >> header.shift); while (index < stop) { if (fullStream.ReadByte() == highBits) { offset = header.posData + index * table.RowSize; return true; } index++; } offset = 0; return false; } } /// /// Hot table stream (CLR 4.0) /// sealed class HotTableStreamCLR40 : HotTableStream { TableHeader[] tableHeaders; class TableHeader { public uint numRows; public long posTable1; public long posTable2; public long posIndexes; public long posData; public int shift; public uint mask; } /// /// Constructor /// /// Data stream /// Offset in of start of the /// hot table directory header public HotTableStreamCLR40(IImageStream fullStream, long baseOffset) : base(fullStream, baseOffset) { } /// [HandleProcessCorruptedStateExceptions, SecurityCritical] // Req'd on .NET 4.0 public override void Initialize(long mask) { tableHeaders = new TableHeader[MAX_TABLES]; for (int i = 0; i < tableHeaders.Length; i++) { fullStream.Position = baseOffset + 4 + i * 4; int headerOffs = fullStream.ReadInt32(); if (headerOffs == 0) continue; var headerBaseOffs = (baseOffset + headerOffs) & mask; fullStream.Position = headerBaseOffs; try { var header = new TableHeader { numRows = fullStream.ReadUInt32(), posTable1 = AddOffsets(mask, headerBaseOffs, fullStream.ReadInt32()), posTable2 = (headerBaseOffs + fullStream.ReadInt32()) & mask, posIndexes = (headerBaseOffs + fullStream.ReadInt32()) & mask, posData = (headerBaseOffs + fullStream.ReadInt32()) & mask, shift = fullStream.ReadUInt16(), }; header.mask = (1U << header.shift) - 1; tableHeaders[i] = header; } // Ignore exceptions. The CLR only reads these values when needed. Assume // that this was invalid data that the CLR will never read anyway. catch (AccessViolationException) { } catch (IOException) { } } } /// protected override bool GetRowOffset(MDTable table, uint rid, out long offset) { offset = 0; if ((uint)table.Table >= (uint)tableHeaders.Length) return false; var header = tableHeaders[(int)table.Table]; if (header == null) return false; // Check whether the whole table is in memory if (header.posTable1 == 0) { offset = header.posData + (rid - 1) * table.RowSize; return true; } fullStream.Position = header.posTable1 + (rid & header.mask) * 2; int index = fullStream.ReadUInt16(); int stop = fullStream.ReadUInt16(); fullStream.Position = header.posTable2 + index; byte highBits = (byte)(rid >> header.shift); while (index < stop) { if (fullStream.ReadByte() == highBits) { index = fullStream.ReadUInt16At(header.posIndexes + index * 2); offset = header.posData + index * table.RowSize; return true; } index++; } offset = 0; return false; } } } dnlib-2.1_VS2010/src/DotNet/MD/IMetaData.cs000066400000000000000000000325541325033663500200020ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.PE; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet.MD { /// /// Interface to access the .NET metadata /// public interface IMetaData : IDisposable { /// /// true if the compressed (normal) metadata is used, false if the non-compressed /// (Edit N' Continue) metadata is used. This can be false even if the table stream /// is #~ but that's very uncommon. /// bool IsCompressed { get; } /// /// true if this is standalone Portable PDB metadata /// bool IsStandalonePortablePdb { get; } /// /// Gets the .NET header /// ImageCor20Header ImageCor20Header { get; } /// /// Gets the major version number found in the MetaData header /// ushort MajorVersion { get; } /// /// Gets the minor version number found in the MetaData header /// ushort MinorVersion { get; } /// /// Gets the version string found in the MetaData header /// string VersionString { get; } /// /// Gets the /// IPEImage PEImage { get; } /// /// Gets the metadata header /// MetaDataHeader MetaDataHeader { get; } /// /// Returns the #Strings stream or a default empty one if it's not present /// StringsStream StringsStream { get; } /// /// Returns the #US stream or a default empty one if it's not present /// USStream USStream { get; } /// /// Returns the #Blob stream or a default empty one if it's not present /// BlobStream BlobStream { get; } /// /// Returns the #GUID stream or a default empty one if it's not present /// GuidStream GuidStream { get; } /// /// Returns the #~ or #- tables stream /// TablesStream TablesStream { get; } /// /// Returns the #Pdb stream or null if it's not a standalone portable PDB file /// PdbStream PdbStream { get; } /// /// Gets all streams /// ThreadSafe.IList AllStreams { get; } /// /// Gets a list of all the valid TypeDef rids. It's usually every rid in the /// TypeDef table, but could be less if a type has been deleted. /// RidList GetTypeDefRidList(); /// /// Gets a list of all the valid ExportedType rids. It's usually every rid in the /// ExportedType table, but could be less if a type has been deleted. /// RidList GetExportedTypeRidList(); /// /// Gets the Field rid list /// /// TypeDef rid /// A new instance RidList GetFieldRidList(uint typeDefRid); /// /// Gets the Method rid list /// /// TypeDef rid /// A new instance RidList GetMethodRidList(uint typeDefRid); /// /// Gets the Param rid list /// /// Method rid /// A new instance RidList GetParamRidList(uint methodRid); /// /// Gets the Event rid list /// /// EventMap rid /// A new instance RidList GetEventRidList(uint eventMapRid); /// /// Gets the Property rid list /// /// PropertyMap rid /// A new instance RidList GetPropertyRidList(uint propertyMapRid); /// /// Finds all InterfaceImpl rids owned by /// /// Owner TypeDef rid /// A instance containing the valid InterfaceImpl rids RidList GetInterfaceImplRidList(uint typeDefRid); /// /// Finds all GenericParam rids owned by in table /// /// A TypeOrMethodDef table /// Owner rid /// A instance containing the valid GenericParam rids RidList GetGenericParamRidList(Table table, uint rid); /// /// Finds all GenericParamConstraint rids owned by /// /// Owner GenericParam rid /// A instance containing the valid GenericParamConstraint rids RidList GetGenericParamConstraintRidList(uint genericParamRid); /// /// Finds all CustomAttribute rids owned by in table /// /// A HasCustomAttribute table /// Owner rid /// A instance containing the valid CustomAttribute rids RidList GetCustomAttributeRidList(Table table, uint rid); /// /// Finds all DeclSecurity rids owned by in table /// /// A HasDeclSecurity table /// Owner rid /// A instance containing the valid DeclSecurity rids RidList GetDeclSecurityRidList(Table table, uint rid); /// /// Finds all MethodSemantics rids owned by in table /// /// A HasSemantic table /// Owner rid /// A instance containing the valid MethodSemantics rids RidList GetMethodSemanticsRidList(Table table, uint rid); /// /// Finds all MethodImpl rids owned by /// /// Owner TypeDef rid /// A instance containing the valid MethodImpl rids RidList GetMethodImplRidList(uint typeDefRid); /// /// Finds a ClassLayout rid /// /// Owner TypeDef rid /// The ClassLayout rid or 0 if is invalid /// or if it has no row in the ClassLayout table. uint GetClassLayoutRid(uint typeDefRid); /// /// Finds a FieldLayout rid /// /// Owner Field rid /// The FieldLayout rid or 0 if is invalid /// or if it has no row in the FieldLayout table. uint GetFieldLayoutRid(uint fieldRid); /// /// Finds a FieldMarshal rid /// /// A HasFieldMarshal table /// Owner rid /// The FieldMarshal rid or 0 if is invalid /// or if it has no row in the FieldMarshal table. uint GetFieldMarshalRid(Table table, uint rid); /// /// Finds a FieldRVA rid /// /// Owner Field rid /// The FieldRVA rid or 0 if is invalid /// or if it has no row in the FieldRVA table. uint GetFieldRVARid(uint fieldRid); /// /// Finds an ImplMap rid /// /// A MemberForwarded table /// Owner rid /// The ImplMap rid or 0 if is invalid /// or if it has no row in the ImplMap table. uint GetImplMapRid(Table table, uint rid); /// /// Finds a NestedClass rid /// /// Owner TypeDef rid /// The NestedClass rid or 0 if is invalid /// or if it has no row in the NestedClass table. uint GetNestedClassRid(uint typeDefRid); /// /// Finds an EventMap rid /// /// Owner TypeDef rid /// The EventMap rid or 0 if is invalid /// or if it has no row in the EventMap table. uint GetEventMapRid(uint typeDefRid); /// /// Finds a PropertyMap rid /// /// Owner TypeDef rid /// The PropertyMap rid or 0 if is invalid /// or if it has no row in the PropertyMap table. uint GetPropertyMapRid(uint typeDefRid); /// /// Finds a Constant rid /// /// A HasConstant table /// Owner rid /// The Constant rid or 0 if is invalid /// or if it has no row in the Constant table. uint GetConstantRid(Table table, uint rid); /// /// Returns the owner TypeDef rid /// /// A Field rid /// The owner TypeDef rid or 0 if is invalid /// or if it has no owner. uint GetOwnerTypeOfField(uint fieldRid); /// /// Returns the owner TypeDef rid /// /// A Method rid /// The owner TypeDef rid or 0 if is invalid /// or if it has no owner. uint GetOwnerTypeOfMethod(uint methodRid); /// /// Returns the owner TypeDef rid /// /// A Event rid /// The owner TypeDef rid or 0 if is invalid /// or if it has no owner. uint GetOwnerTypeOfEvent(uint eventRid); /// /// Returns the owner TypeDef rid /// /// A Property rid /// The owner TypeDef rid or 0 if is invalid /// or if it has no owner. uint GetOwnerTypeOfProperty(uint propertyRid); /// /// Returns the owner TypeOrMethodDef rid /// /// A GenericParam rid /// The owner TypeOrMethodDef rid or 0 if is /// invalid or if it has no owner. uint GetOwnerOfGenericParam(uint gpRid); /// /// Returns the owner GenericParam rid /// /// A GenericParamConstraint rid /// The owner GenericParam rid or 0 if is /// invalid or if it has no owner. uint GetOwnerOfGenericParamConstraint(uint gpcRid); /// /// Returns the owner Method rid /// /// A Param rid /// The owner Method rid or 0 if is invalid /// or if it has no owner. uint GetOwnerOfParam(uint paramRid); /// /// Gets a list of all nested classes owned by /// /// A TypeDef rid /// A new instance RidList GetNestedClassRidList(uint typeDefRid); /// /// Gets a list of all non-nested classes. A type is a non-nested type if /// returns an empty list. /// /// A new instance RidList GetNonNestedClassRidList(); /// /// Finds all LocalScope rids owned by /// /// Owner Method rid /// A instance containing the valid LocalScope rids RidList GetLocalScopeRidList(uint methodRid); /// /// Gets the StateMachineMethod rid or 0 if it's not a state machine method /// /// Owner Method rid /// uint GetStateMachineMethodRid(uint methodRid); /// /// Finds all CustomDebugInformation rids owned by in table /// /// A HasCustomDebugInformation table /// Owner rid /// A instance containing the valid CustomDebugInformation rids RidList GetCustomDebugInformationRidList(Table table, uint rid); } } dnlib-2.1_VS2010/src/DotNet/MD/IRowReaders.cs000066400000000000000000000020431325033663500203650ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.MD { /// /// Reads metadata table columns /// public interface IColumnReader { /// /// Reads a column /// /// The table to read from /// Table row id /// The column to read /// Result /// true if was updated, false if /// the column should be read from the original table. bool ReadColumn(MDTable table, uint rid, ColumnInfo column, out uint value); } /// /// Reads table rows /// /// Raw row public interface IRowReader where TRow : class, IRawRow { /// /// Reads a table row /// /// Row id /// The table row or null if its row should be read from the original /// table TRow ReadRow(uint rid); } } dnlib-2.1_VS2010/src/DotNet/MD/ImageCor20Header.cs000066400000000000000000000101721325033663500211420ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.MD { /// /// Represents the IMAGE_COR20_HEADER structure /// public sealed class ImageCor20Header : FileSection { readonly uint cb; readonly ushort majorRuntimeVersion; readonly ushort minorRuntimeVersion; readonly ImageDataDirectory metaData; readonly ComImageFlags flags; readonly uint entryPointToken_or_RVA; readonly ImageDataDirectory resources; readonly ImageDataDirectory strongNameSignature; readonly ImageDataDirectory codeManagerTable; readonly ImageDataDirectory vtableFixups; readonly ImageDataDirectory exportAddressTableJumps; readonly ImageDataDirectory managedNativeHeader; /// /// Returns true if it has a native header /// public bool HasNativeHeader { get { return (flags & ComImageFlags.ILLibrary) != 0; } } /// /// Returns the IMAGE_COR20_HEADER.cb field /// public uint CB { get { return cb; } } /// /// Returns the IMAGE_COR20_HEADER.MajorRuntimeVersion field /// public ushort MajorRuntimeVersion { get { return majorRuntimeVersion; } } /// /// Returns the IMAGE_COR20_HEADER.MinorRuntimeVersion field /// public ushort MinorRuntimeVersion { get { return minorRuntimeVersion; } } /// /// Returns the IMAGE_COR20_HEADER.MetaData field /// public ImageDataDirectory MetaData { get { return metaData; } } /// /// Returns the IMAGE_COR20_HEADER.Flags field /// public ComImageFlags Flags { get { return flags; } } /// /// Returns the IMAGE_COR20_HEADER.EntryPointToken/EntryPointTokenRVA field /// public uint EntryPointToken_or_RVA { get { return entryPointToken_or_RVA; } } /// /// Returns the IMAGE_COR20_HEADER.Resources field /// public ImageDataDirectory Resources { get { return resources; } } /// /// Returns the IMAGE_COR20_HEADER.StrongNameSignature field /// public ImageDataDirectory StrongNameSignature { get { return strongNameSignature; } } /// /// Returns the IMAGE_COR20_HEADER.CodeManagerTable field /// public ImageDataDirectory CodeManagerTable { get { return codeManagerTable; } } /// /// Returns the IMAGE_COR20_HEADER.VTableFixups field /// public ImageDataDirectory VTableFixups { get { return vtableFixups; } } /// /// Returns the IMAGE_COR20_HEADER.ExportAddressTableJumps field /// public ImageDataDirectory ExportAddressTableJumps { get { return exportAddressTableJumps; } } /// /// Returns the IMAGE_COR20_HEADER.ManagedNativeHeader field /// public ImageDataDirectory ManagedNativeHeader { get { return managedNativeHeader; } } /// /// Constructor /// /// PE file reader pointing to the start of this section /// Verify section /// Thrown if verification fails public ImageCor20Header(IImageStream reader, bool verify) { SetStartOffset(reader); this.cb = reader.ReadUInt32(); if (verify && this.cb < 0x48) throw new BadImageFormatException("Invalid IMAGE_COR20_HEADER.cb value"); this.majorRuntimeVersion = reader.ReadUInt16(); this.minorRuntimeVersion = reader.ReadUInt16(); this.metaData = new ImageDataDirectory(reader, verify); this.flags = (ComImageFlags)reader.ReadUInt32(); this.entryPointToken_or_RVA = reader.ReadUInt32(); this.resources = new ImageDataDirectory(reader, verify); this.strongNameSignature = new ImageDataDirectory(reader, verify); this.codeManagerTable = new ImageDataDirectory(reader, verify); this.vtableFixups = new ImageDataDirectory(reader, verify); this.exportAddressTableJumps = new ImageDataDirectory(reader, verify); this.managedNativeHeader = new ImageDataDirectory(reader, verify); SetEndoffset(reader); } } } dnlib-2.1_VS2010/src/DotNet/MD/MDHeaderRuntimeVersion.cs000066400000000000000000000042141325033663500225240ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.MD { /// /// Version strings found in the meta data header /// public static class MDHeaderRuntimeVersion { /// /// MS CLR 1.0 version string (.NET 1.0) /// public const string MS_CLR_10 = "v1.0.3705"; /// /// MS CLR 1.0 version string (.NET 1.0). This is an incorrect version that shouldn't be used. /// public const string MS_CLR_10_X86RETAIL = "v1.x86ret"; /// /// MS CLR 1.0 version string (.NET 1.0). This is an incorrect version that shouldn't be used. /// public const string MS_CLR_10_RETAIL = "retail"; /// /// MS CLR 1.0 version string (.NET 1.0). This is an incorrect version that shouldn't be used. /// public const string MS_CLR_10_COMPLUS = "COMPLUS"; /// /// MS CLR 1.1 version string (.NET 1.1) /// public const string MS_CLR_11 = "v1.1.4322"; /// /// MS CLR 2.0 version string (.NET 2.0-3.5) /// public const string MS_CLR_20 = "v2.0.50727"; /// /// MS CLR 4.0 version string (.NET 4.0-4.5) /// public const string MS_CLR_40 = "v4.0.30319"; /// /// MS CLR 1.0 any version /// public const string MS_CLR_10_PREFIX = "v1.0"; /// /// MS CLR 1.0 any version /// public const string MS_CLR_10_PREFIX_X86RETAIL = "v1.x86"; /// /// MS CLR 1.1 any version /// public const string MS_CLR_11_PREFIX = "v1.1"; /// /// MS CLR 2.0 any version /// public const string MS_CLR_20_PREFIX = "v2.0"; /// /// MS CLR 4.0 any version /// public const string MS_CLR_40_PREFIX = "v4.0"; /// /// ECMA 2002 version string /// public const string ECMA_2002 = "Standard CLI 2002"; /// /// ECMA 2005 version string /// public const string ECMA_2005 = "Standard CLI 2005"; /// /// Portable PDB v1.0 /// public const string PORTABLE_PDB_V1_0 = "PDB v1.0"; } } dnlib-2.1_VS2010/src/DotNet/MD/MDStreamFlags.cs000066400000000000000000000013551325033663500206350ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet.MD { /// /// MDStream flags /// [Flags] public enum MDStreamFlags : byte { /// #Strings stream is big and requires 4 byte offsets BigStrings = 1, /// #GUID stream is big and requires 4 byte offsets BigGUID = 2, /// #Blob stream is big and requires 4 byte offsets BigBlob = 4, /// Padding = 8, /// DeltaOnly = 0x20, /// Extra data follows the row counts ExtraData = 0x40, /// Set if certain tables can contain deleted rows. The name column (if present) is set to "_Deleted" HasDelete = 0x80, } } dnlib-2.1_VS2010/src/DotNet/MD/MDTable.cs000066400000000000000000000061601325033663500174530ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using dnlib.IO; namespace dnlib.DotNet.MD { /// /// A MD table (eg. Method table) /// [DebuggerDisplay("DL:{imageStream.Length} R:{numRows} RS:{tableInfo.RowSize} C:{Count} {tableInfo.Name}")] public sealed class MDTable : IDisposable, IFileSection { readonly Table table; uint numRows; TableInfo tableInfo; IImageStream imageStream; // Fix for VS2015 expression evaluator: "The debugger is unable to evaluate this expression" int Count { get { return tableInfo.Columns.Count; } } /// public FileOffset StartOffset { get { return imageStream.FileOffset; } } /// public FileOffset EndOffset { get { return imageStream.FileOffset + imageStream.Length; } } /// /// Gets the table /// public Table Table { get { return table; } } /// /// Gets the name of this table /// public string Name { get { return tableInfo.Name; } } /// /// Returns total number of rows /// public uint Rows { get { return numRows; } } /// /// Gets the total size in bytes of one row in this table /// public uint RowSize { get { return (uint)tableInfo.RowSize; } } /// /// Returns all the columns /// public IList Columns { get { return tableInfo.Columns; } } /// /// Returns true if there are no valid rows /// public bool IsEmpty { get { return numRows == 0; } } /// /// Returns info about this table /// public TableInfo TableInfo { get { return tableInfo; } } /// /// The stream that can access all the rows in this table /// internal IImageStream ImageStream { get { return imageStream; } set { var ims = imageStream; if (ims == value) return; if (ims != null) ims.Dispose(); imageStream = value; } } /// /// Constructor /// /// The table /// Number of rows in this table /// Info about this table internal MDTable(Table table, uint numRows, TableInfo tableInfo) { this.table = table; this.numRows = numRows; this.tableInfo = tableInfo; } internal IImageStream CloneImageStream() { return imageStream.Clone(); } /// /// Checks whether the row exists /// /// Row ID public bool IsValidRID(uint rid) { return rid != 0 && rid <= numRows; } /// /// Checks whether the row does not exist /// /// Row ID public bool IsInvalidRID(uint rid) { return rid == 0 || rid > numRows; } /// public void Dispose() { var ims = imageStream; if (ims != null) ims.Dispose(); numRows = 0; tableInfo = null; imageStream = null; } } } dnlib-2.1_VS2010/src/DotNet/MD/MetaData.cs000066400000000000000000000676541325033663500177020ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using dnlib.IO; using dnlib.PE; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet.MD { /// /// Common base class for #~ and #- metadata classes /// abstract class MetaData : IMetaData { /// /// The PE image /// protected IPEImage peImage; /// /// The .NET header /// protected ImageCor20Header cor20Header; /// /// The MD header /// protected MetaDataHeader mdHeader; /// /// The #Strings stream /// protected StringsStream stringsStream; /// /// The #US stream /// protected USStream usStream; /// /// The #Blob stream /// protected BlobStream blobStream; /// /// The #GUID stream /// protected GuidStream guidStream; /// /// The #~ or #- stream /// protected TablesStream tablesStream; /// /// The #Pdb stream /// protected PdbStream pdbStream; /// /// All the streams that are present in the PE image /// protected ThreadSafe.IList allStreams; /// public bool IsStandalonePortablePdb { get { return isStandalonePortablePdb; } } /// true if this is standalone Portable PDB metadata protected readonly bool isStandalonePortablePdb; uint[] fieldRidToTypeDefRid; uint[] methodRidToTypeDefRid; uint[] eventRidToTypeDefRid; uint[] propertyRidToTypeDefRid; uint[] gpRidToOwnerRid; uint[] gpcRidToOwnerRid; uint[] paramRidToOwnerRid; Dictionary typeDefRidToNestedClasses; RandomRidList nonNestedTypes; /// /// Sorts a table by key column /// protected sealed class SortedTable { RowInfo[] rows; /// /// Remembers rid and key /// [DebuggerDisplay("{rid} {key}")] struct RowInfo : IComparable { public readonly uint rid; public readonly uint key; /// /// Constructor /// /// Row ID /// Key public RowInfo(uint rid, uint key) { this.rid = rid; this.key = key; } /// public int CompareTo(RowInfo other) { if (key < other.key) return -1; if (key > other.key) return 1; return rid.CompareTo(other.rid); } } /// /// Constructor /// /// The MD table /// Index of key column public SortedTable(MDTable mdTable, int keyColIndex) { InitializeKeys(mdTable, keyColIndex); Array.Sort(rows); } void InitializeKeys(MDTable mdTable, int keyColIndex) { var keyColumn = mdTable.TableInfo.Columns[keyColIndex]; rows = new RowInfo[mdTable.Rows + 1]; if (mdTable.Rows == 0) return; using (var reader = mdTable.CloneImageStream()) { reader.Position = keyColumn.Offset; int increment = mdTable.TableInfo.RowSize - keyColumn.Size; for (uint i = 1; i <= mdTable.Rows; i++) { rows[i] = new RowInfo(i, keyColumn.Read(reader)); if (i < mdTable.Rows) reader.Position += increment; } } } /// /// Binary searches for a row with a certain key /// /// The key /// The row or 0 if not found int BinarySearch(uint key) { int lo = 1, hi = rows.Length - 1; while (lo <= hi && hi != -1) { int curr = (lo + hi) / 2; uint key2 = rows[curr].key; if (key == key2) return curr; if (key2 > key) hi = curr - 1; else lo = curr + 1; } return 0; } /// /// Find all rids that contain /// /// The key /// A new instance public RidList FindAllRows(uint key) { int startIndex = BinarySearch(key); if (startIndex == 0) return RidList.Empty; int endIndex = startIndex + 1; for (; startIndex > 1; startIndex--) { if (key != rows[startIndex - 1].key) break; } for (; endIndex < rows.Length; endIndex++) { if (key != rows[endIndex].key) break; } var list = new RandomRidList(endIndex - startIndex); for (int i = startIndex; i < endIndex; i++) list.Add(rows[i].rid); return list; } } SortedTable eventMapSortedTable; SortedTable propertyMapSortedTable; /// public abstract bool IsCompressed { get; } /// public ImageCor20Header ImageCor20Header { get { return cor20Header; } } /// public ushort MajorVersion { get { return mdHeader.MajorVersion; } } /// public ushort MinorVersion { get { return mdHeader.MinorVersion; } } /// public string VersionString { get { return mdHeader.VersionString; } } /// public IPEImage PEImage { get { return peImage; } } /// public MetaDataHeader MetaDataHeader { get { return mdHeader; } } /// public StringsStream StringsStream { get { return stringsStream; } } /// public USStream USStream { get { return usStream; } } /// public BlobStream BlobStream { get { return blobStream; } } /// public GuidStream GuidStream { get { return guidStream; } } /// public TablesStream TablesStream { get { return tablesStream; } } /// public PdbStream PdbStream { get { return pdbStream; } } /// public ThreadSafe.IList AllStreams { get { return allStreams; } } /// /// Constructor /// /// The PE image /// The .NET header /// The MD header protected MetaData(IPEImage peImage, ImageCor20Header cor20Header, MetaDataHeader mdHeader) { try { this.allStreams = ThreadSafeListCreator.Create(); this.peImage = peImage; this.cor20Header = cor20Header; this.mdHeader = mdHeader; isStandalonePortablePdb = false; } catch { if (peImage != null) peImage.Dispose(); throw; } } internal MetaData(MetaDataHeader mdHeader, bool isStandalonePortablePdb) { this.allStreams = ThreadSafeListCreator.Create(); this.peImage = null; this.cor20Header = null; this.mdHeader = mdHeader; this.isStandalonePortablePdb = isStandalonePortablePdb; } /// /// Initializes the metadata, tables, streams /// public void Initialize(IImageStream mdStream) { InitializeInternal(mdStream); if (tablesStream == null) throw new BadImageFormatException("Missing MD stream"); if (isStandalonePortablePdb && pdbStream == null) throw new BadImageFormatException("Missing #Pdb stream"); InitializeNonExistentHeaps(); } /// /// Creates empty heap objects if they're not present in the metadata /// protected void InitializeNonExistentHeaps() { if (stringsStream == null) stringsStream = new StringsStream(); if (usStream == null) usStream = new USStream(); if (blobStream == null) blobStream = new BlobStream(); if (guidStream == null) guidStream = new GuidStream(); } /// /// Called by /// protected abstract void InitializeInternal(IImageStream mdStream); /// public virtual RidList GetTypeDefRidList() { return new ContiguousRidList(1, tablesStream.TypeDefTable.Rows); } /// public virtual RidList GetExportedTypeRidList() { return new ContiguousRidList(1, tablesStream.ExportedTypeTable.Rows); } /// public abstract RidList GetFieldRidList(uint typeDefRid); /// public abstract RidList GetMethodRidList(uint typeDefRid); /// public abstract RidList GetParamRidList(uint methodRid); /// public abstract RidList GetEventRidList(uint eventMapRid); /// public abstract RidList GetPropertyRidList(uint propertyMapRid); /// /// Binary searches the table for a rid whose key column at index /// is equal to . The /// has acquired its lock so only *_NoLock methods /// may be called. /// /// Table to search /// Key column index /// Key /// The rid of the found row, or 0 if none found protected abstract uint BinarySearch_NoLock(MDTable tableSource, int keyColIndex, uint key); /// /// Finds all rows owned by in table /// whose index is /// /// Table to search /// Key column index /// Key /// A instance protected RidList FindAllRows(MDTable tableSource, int keyColIndex, uint key) { #if THREAD_SAFE tablesStream.theLock.EnterWriteLock(); try { #endif uint startRid = BinarySearch_NoLock(tableSource, keyColIndex, key); if (tableSource.IsInvalidRID(startRid)) return RidList.Empty; uint endRid = startRid + 1; var column = tableSource.TableInfo.Columns[keyColIndex]; for (; startRid > 1; startRid--) { uint key2; if (!tablesStream.ReadColumn_NoLock(tableSource, startRid - 1, column, out key2)) break; // Should never happen since startRid is valid if (key != key2) break; } for (; endRid <= tableSource.Rows; endRid++) { uint key2; if (!tablesStream.ReadColumn_NoLock(tableSource, endRid, column, out key2)) break; // Should never happen since endRid is valid if (key != key2) break; } return new ContiguousRidList(startRid, endRid - startRid); #if THREAD_SAFE } finally { tablesStream.theLock.ExitWriteLock(); } #endif } /// /// Finds all rows owned by in table /// whose index is . Should be called if /// could be unsorted. /// /// Table to search /// Key column index /// Key /// A instance protected virtual RidList FindAllRowsUnsorted(MDTable tableSource, int keyColIndex, uint key) { return FindAllRows(tableSource, keyColIndex, key); } /// public RidList GetInterfaceImplRidList(uint typeDefRid) { return FindAllRowsUnsorted(tablesStream.InterfaceImplTable, 0, typeDefRid); } /// public RidList GetGenericParamRidList(Table table, uint rid) { uint codedToken; if (!CodedToken.TypeOrMethodDef.Encode(new MDToken(table, rid), out codedToken)) return RidList.Empty; return FindAllRowsUnsorted(tablesStream.GenericParamTable, 2, codedToken); } /// public RidList GetGenericParamConstraintRidList(uint genericParamRid) { return FindAllRowsUnsorted(tablesStream.GenericParamConstraintTable, 0, genericParamRid); } /// public RidList GetCustomAttributeRidList(Table table, uint rid) { uint codedToken; if (!CodedToken.HasCustomAttribute.Encode(new MDToken(table, rid), out codedToken)) return RidList.Empty; return FindAllRowsUnsorted(tablesStream.CustomAttributeTable, 0, codedToken); } /// public RidList GetDeclSecurityRidList(Table table, uint rid) { uint codedToken; if (!CodedToken.HasDeclSecurity.Encode(new MDToken(table, rid), out codedToken)) return RidList.Empty; return FindAllRowsUnsorted(tablesStream.DeclSecurityTable, 1, codedToken); } /// public RidList GetMethodSemanticsRidList(Table table, uint rid) { uint codedToken; if (!CodedToken.HasSemantic.Encode(new MDToken(table, rid), out codedToken)) return RidList.Empty; return FindAllRowsUnsorted(tablesStream.MethodSemanticsTable, 2, codedToken); } /// public RidList GetMethodImplRidList(uint typeDefRid) { return FindAllRowsUnsorted(tablesStream.MethodImplTable, 0, typeDefRid); } /// public uint GetClassLayoutRid(uint typeDefRid) { var list = FindAllRowsUnsorted(tablesStream.ClassLayoutTable, 2, typeDefRid); return list.Length == 0 ? 0 : list[0]; } /// public uint GetFieldLayoutRid(uint fieldRid) { var list = FindAllRowsUnsorted(tablesStream.FieldLayoutTable, 1, fieldRid); return list.Length == 0 ? 0 : list[0]; } /// public uint GetFieldMarshalRid(Table table, uint rid) { uint codedToken; if (!CodedToken.HasFieldMarshal.Encode(new MDToken(table, rid), out codedToken)) return 0; var list = FindAllRowsUnsorted(tablesStream.FieldMarshalTable, 0, codedToken); return list.Length == 0 ? 0 : list[0]; } /// public uint GetFieldRVARid(uint fieldRid) { var list = FindAllRowsUnsorted(tablesStream.FieldRVATable, 1, fieldRid); return list.Length == 0 ? 0 : list[0]; } /// public uint GetImplMapRid(Table table, uint rid) { uint codedToken; if (!CodedToken.MemberForwarded.Encode(new MDToken(table, rid), out codedToken)) return 0; var list = FindAllRowsUnsorted(tablesStream.ImplMapTable, 1, codedToken); return list.Length == 0 ? 0 : list[0]; } /// public uint GetNestedClassRid(uint typeDefRid) { var list = FindAllRowsUnsorted(tablesStream.NestedClassTable, 0, typeDefRid); return list.Length == 0 ? 0 : list[0]; } /// public uint GetEventMapRid(uint typeDefRid) { // The EventMap and PropertyMap tables can only be trusted to be sorted if it's // an NGen image and it's the normal #- stream. The IsSorted bit must not be used // to check whether the tables are sorted. See coreclr: md/inc/metamodel.h / IsVerified() if (eventMapSortedTable == null) Interlocked.CompareExchange(ref eventMapSortedTable, new SortedTable(tablesStream.EventMapTable, 0), null); var list = eventMapSortedTable.FindAllRows(typeDefRid); return list.Length == 0 ? 0 : list[0]; } /// public uint GetPropertyMapRid(uint typeDefRid) { // Always unsorted, see comment in GetEventMapRid() above if (propertyMapSortedTable == null) Interlocked.CompareExchange(ref propertyMapSortedTable, new SortedTable(tablesStream.PropertyMapTable, 0), null); var list = propertyMapSortedTable.FindAllRows(typeDefRid); return list.Length == 0 ? 0 : list[0]; } /// public uint GetConstantRid(Table table, uint rid) { uint codedToken; if (!CodedToken.HasConstant.Encode(new MDToken(table, rid), out codedToken)) return 0; var list = FindAllRowsUnsorted(tablesStream.ConstantTable, 2, codedToken); return list.Length == 0 ? 0 : list[0]; } /// public uint GetOwnerTypeOfField(uint fieldRid) { if (fieldRidToTypeDefRid == null) InitializeInverseFieldOwnerRidList(); uint index = fieldRid - 1; if (index >= fieldRidToTypeDefRid.LongLength) return 0; return fieldRidToTypeDefRid[index]; } void InitializeInverseFieldOwnerRidList() { if (fieldRidToTypeDefRid != null) return; var newFieldRidToTypeDefRid = new uint[tablesStream.FieldTable.Rows]; var ownerList = GetTypeDefRidList(); for (uint i = 0; i < ownerList.Length; i++) { var ownerRid = ownerList[i]; var fieldList = GetFieldRidList(ownerRid); for (uint j = 0; j < fieldList.Length; j++) { uint ridIndex = fieldList[j] - 1; if (newFieldRidToTypeDefRid[ridIndex] != 0) continue; newFieldRidToTypeDefRid[ridIndex] = ownerRid; } } Interlocked.CompareExchange(ref fieldRidToTypeDefRid, newFieldRidToTypeDefRid, null); } /// public uint GetOwnerTypeOfMethod(uint methodRid) { if (methodRidToTypeDefRid == null) InitializeInverseMethodOwnerRidList(); uint index = methodRid - 1; if (index >= methodRidToTypeDefRid.LongLength) return 0; return methodRidToTypeDefRid[index]; } void InitializeInverseMethodOwnerRidList() { if (methodRidToTypeDefRid != null) return; var newMethodRidToTypeDefRid = new uint[tablesStream.MethodTable.Rows]; var ownerList = GetTypeDefRidList(); for (uint i = 0; i < ownerList.Length; i++) { var ownerRid = ownerList[i]; var methodList = GetMethodRidList(ownerRid); for (uint j = 0; j < methodList.Length; j++) { uint ridIndex = methodList[j] - 1; if (newMethodRidToTypeDefRid[ridIndex] != 0) continue; newMethodRidToTypeDefRid[ridIndex] = ownerRid; } } Interlocked.CompareExchange(ref methodRidToTypeDefRid, newMethodRidToTypeDefRid, null); } /// public uint GetOwnerTypeOfEvent(uint eventRid) { if (eventRidToTypeDefRid == null) InitializeInverseEventOwnerRidList(); uint index = eventRid - 1; if (index >= eventRidToTypeDefRid.LongLength) return 0; return eventRidToTypeDefRid[index]; } void InitializeInverseEventOwnerRidList() { if (eventRidToTypeDefRid != null) return; var newEventRidToTypeDefRid = new uint[tablesStream.EventTable.Rows]; var ownerList = GetTypeDefRidList(); for (uint i = 0; i < ownerList.Length; i++) { var ownerRid = ownerList[i]; var eventList = GetEventRidList(GetEventMapRid(ownerRid)); for (uint j = 0; j < eventList.Length; j++) { uint ridIndex = eventList[j] - 1; if (newEventRidToTypeDefRid[ridIndex] != 0) continue; newEventRidToTypeDefRid[ridIndex] = ownerRid; } } Interlocked.CompareExchange(ref eventRidToTypeDefRid, newEventRidToTypeDefRid, null); } /// public uint GetOwnerTypeOfProperty(uint propertyRid) { if (propertyRidToTypeDefRid == null) InitializeInversePropertyOwnerRidList(); uint index = propertyRid - 1; if (index >= propertyRidToTypeDefRid.LongLength) return 0; return propertyRidToTypeDefRid[index]; } void InitializeInversePropertyOwnerRidList() { if (propertyRidToTypeDefRid != null) return; var newPropertyRidToTypeDefRid = new uint[tablesStream.PropertyTable.Rows]; var ownerList = GetTypeDefRidList(); for (uint i = 0; i < ownerList.Length; i++) { var ownerRid = ownerList[i]; var propertyList = GetPropertyRidList(GetPropertyMapRid(ownerRid)); for (uint j = 0; j < propertyList.Length; j++) { uint ridIndex = propertyList[j] - 1; if (newPropertyRidToTypeDefRid[ridIndex] != 0) continue; newPropertyRidToTypeDefRid[ridIndex] = ownerRid; } } Interlocked.CompareExchange(ref propertyRidToTypeDefRid, newPropertyRidToTypeDefRid, null); } /// public uint GetOwnerOfGenericParam(uint gpRid) { // Don't use GenericParam.Owner column. If the GP table is sorted, it's // possible to have two blocks of GPs with the same owner. Only one of the // blocks is the "real" generic params for the owner. Of course, rarely // if ever will this occur, but could happen if some obfuscator has // added it. if (gpRidToOwnerRid == null) InitializeInverseGenericParamOwnerRidList(); uint index = gpRid - 1; if (index >= gpRidToOwnerRid.LongLength) return 0; return gpRidToOwnerRid[index]; } void InitializeInverseGenericParamOwnerRidList() { if (gpRidToOwnerRid != null) return; var gpTable = tablesStream.GenericParamTable; var newGpRidToOwnerRid = new uint[gpTable.Rows]; // Find all owners by reading the GenericParam.Owner column var ownerCol = gpTable.TableInfo.Columns[2]; var ownersDict = new Dictionary(); #if THREAD_SAFE tablesStream.theLock.EnterWriteLock(); try { #endif for (uint rid = 1; rid <= gpTable.Rows; rid++) { uint owner; if (!tablesStream.ReadColumn_NoLock(gpTable, rid, ownerCol, out owner)) continue; ownersDict[owner] = true; } #if THREAD_SAFE } finally { tablesStream.theLock.ExitWriteLock(); } #endif // Now that we have the owners, find all the generic params they own. An obfuscated // module could have 2+ owners pointing to the same generic param row. var owners = new List(ownersDict.Keys); owners.Sort(); for (int i = 0; i < owners.Count; i++) { uint ownerToken; if (!CodedToken.TypeOrMethodDef.Decode(owners[i], out ownerToken)) continue; var ridList = GetGenericParamRidList(MDToken.ToTable(ownerToken), MDToken.ToRID(ownerToken)); for (uint j = 0; j < ridList.Length; j++) { uint ridIndex = ridList[j] - 1; if (newGpRidToOwnerRid[ridIndex] != 0) continue; newGpRidToOwnerRid[ridIndex] = owners[i]; } } Interlocked.CompareExchange(ref gpRidToOwnerRid, newGpRidToOwnerRid, null); } /// public uint GetOwnerOfGenericParamConstraint(uint gpcRid) { // Don't use GenericParamConstraint.Owner column for the same reason // as described in GetOwnerOfGenericParam(). if (gpcRidToOwnerRid == null) InitializeInverseGenericParamConstraintOwnerRidList(); uint index = gpcRid - 1; if (index >= gpcRidToOwnerRid.LongLength) return 0; return gpcRidToOwnerRid[index]; } void InitializeInverseGenericParamConstraintOwnerRidList() { if (gpcRidToOwnerRid != null) return; var gpcTable = tablesStream.GenericParamConstraintTable; var newGpcRidToOwnerRid = new uint[gpcTable.Rows]; var ownerCol = gpcTable.TableInfo.Columns[0]; var ownersDict = new Dictionary(); #if THREAD_SAFE tablesStream.theLock.EnterWriteLock(); try { #endif for (uint rid = 1; rid <= gpcTable.Rows; rid++) { uint owner; if (!tablesStream.ReadColumn_NoLock(gpcTable, rid, ownerCol, out owner)) continue; ownersDict[owner] = true; } #if THREAD_SAFE } finally { tablesStream.theLock.ExitWriteLock(); } #endif var owners = new List(ownersDict.Keys); owners.Sort(); for (int i = 0; i < owners.Count; i++) { uint ownerToken = owners[i]; var ridList = GetGenericParamConstraintRidList(ownerToken); for (uint j = 0; j < ridList.Length; j++) { uint ridIndex = ridList[j] - 1; if (newGpcRidToOwnerRid[ridIndex] != 0) continue; newGpcRidToOwnerRid[ridIndex] = ownerToken; } } Interlocked.CompareExchange(ref gpcRidToOwnerRid, newGpcRidToOwnerRid, null); } /// public uint GetOwnerOfParam(uint paramRid) { if (paramRidToOwnerRid == null) InitializeInverseParamOwnerRidList(); uint index = paramRid - 1; if (index >= paramRidToOwnerRid.LongLength) return 0; return paramRidToOwnerRid[index]; } void InitializeInverseParamOwnerRidList() { if (paramRidToOwnerRid != null) return; var newParamRidToOwnerRid = new uint[tablesStream.ParamTable.Rows]; var table = tablesStream.MethodTable; for (uint rid = 1; rid <= table.Rows; rid++) { var ridList = GetParamRidList(rid); for (uint j = 0; j < ridList.Length; j++) { uint ridIndex = ridList[j] - 1; if (newParamRidToOwnerRid[ridIndex] != 0) continue; newParamRidToOwnerRid[ridIndex] = rid; } } Interlocked.CompareExchange(ref paramRidToOwnerRid, newParamRidToOwnerRid, null); } /// public RidList GetNestedClassRidList(uint typeDefRid) { if (typeDefRidToNestedClasses == null) InitializeNestedClassesDictionary(); RandomRidList ridList; if (typeDefRidToNestedClasses.TryGetValue(typeDefRid, out ridList)) return ridList; return RidList.Empty; } void InitializeNestedClassesDictionary() { var table = tablesStream.NestedClassTable; var destTable = tablesStream.TypeDefTable; Dictionary validTypeDefRids = null; var typeDefRidList = GetTypeDefRidList(); if (typeDefRidList.Length != destTable.Rows) { validTypeDefRids = new Dictionary((int)typeDefRidList.Length); for (uint i = 0; i < typeDefRidList.Length; i++) validTypeDefRids[typeDefRidList[i]] = true; } var nestedRidsDict = new Dictionary((int)table.Rows); var nestedRids = new List((int)table.Rows); // Need it so we add the rids in correct order for (uint rid = 1; rid <= table.Rows; rid++) { if (validTypeDefRids != null && !validTypeDefRids.ContainsKey(rid)) continue; var row = tablesStream.ReadNestedClassRow(rid); if (row == null) continue; // Should never happen since rid is valid if (!destTable.IsValidRID(row.NestedClass) || !destTable.IsValidRID(row.EnclosingClass)) continue; if (nestedRidsDict.ContainsKey(row.NestedClass)) continue; nestedRidsDict[row.NestedClass] = true; nestedRids.Add(row.NestedClass); } var newTypeDefRidToNestedClasses = new Dictionary(); foreach (var nestedRid in nestedRids) { var row = tablesStream.ReadNestedClassRow(GetNestedClassRid(nestedRid)); if (row == null) continue; RandomRidList ridList; if (!newTypeDefRidToNestedClasses.TryGetValue(row.EnclosingClass, out ridList)) newTypeDefRidToNestedClasses[row.EnclosingClass] = ridList = new RandomRidList(); ridList.Add(nestedRid); } var newNonNestedTypes = new RandomRidList((int)(destTable.Rows - nestedRidsDict.Count)); for (uint rid = 1; rid <= destTable.Rows; rid++) { if (validTypeDefRids != null && !validTypeDefRids.ContainsKey(rid)) continue; if (nestedRidsDict.ContainsKey(rid)) continue; newNonNestedTypes.Add(rid); } Interlocked.CompareExchange(ref nonNestedTypes, newNonNestedTypes, null); // Initialize this one last since it's tested by the callers of this method Interlocked.CompareExchange(ref typeDefRidToNestedClasses, newTypeDefRidToNestedClasses, null); } public RidList GetNonNestedClassRidList() { // Check typeDefRidToNestedClasses and not nonNestedTypes since // InitializeNestedClassesDictionary() writes to typeDefRidToNestedClasses last. if (typeDefRidToNestedClasses == null) InitializeNestedClassesDictionary(); return nonNestedTypes; } public RidList GetLocalScopeRidList(uint methodRid) { return FindAllRows(tablesStream.LocalScopeTable, 0, methodRid); } public uint GetStateMachineMethodRid(uint methodRid) { var list = FindAllRows(tablesStream.StateMachineMethodTable, 0, methodRid); return list.Length == 0 ? 0 : list[0]; } public RidList GetCustomDebugInformationRidList(Table table, uint rid) { uint codedToken; if (!CodedToken.HasCustomDebugInformation.Encode(new MDToken(table, rid), out codedToken)) return RidList.Empty; return FindAllRows(tablesStream.CustomDebugInformationTable, 0, codedToken); } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose method /// /// true if called by protected virtual void Dispose(bool disposing) { if (!disposing) return; Dispose(peImage); Dispose(stringsStream); Dispose(usStream); Dispose(blobStream); Dispose(guidStream); Dispose(tablesStream); var as2 = allStreams; if (as2 != null) { foreach (var stream in as2.GetSafeEnumerable()) Dispose(stream); } peImage = null; cor20Header = null; mdHeader = null; stringsStream = null; usStream = null; blobStream = null; guidStream = null; tablesStream = null; allStreams = null; fieldRidToTypeDefRid = null; methodRidToTypeDefRid = null; typeDefRidToNestedClasses = null; } static void Dispose(IDisposable id) { if (id != null) id.Dispose(); } } } dnlib-2.1_VS2010/src/DotNet/MD/MetaDataCreator.cs000066400000000000000000000160621325033663500212050ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.MD { /// /// Low level access to a .NET file's metadata /// public static class MetaDataCreator { enum MetaDataType { Unknown, Compressed, // #~ (normal) ENC, // #- (edit and continue) } /// /// Create a instance /// /// The file to load /// A new instance internal static MetaData Load(string fileName) { IPEImage peImage = null; try { return Load(peImage = new PEImage(fileName)); } catch { if (peImage != null) peImage.Dispose(); throw; } } /// /// Create a instance /// /// The .NET file data /// A new instance internal static MetaData Load(byte[] data) { IPEImage peImage = null; try { return Load(peImage = new PEImage(data)); } catch { if (peImage != null) peImage.Dispose(); throw; } } /// /// Create a instance /// /// Address of a .NET file in memory /// A new instance internal static MetaData Load(IntPtr addr) { IPEImage peImage = null; // We don't know what layout it is. Memory is more common so try that first. try { return Load(peImage = new PEImage(addr, ImageLayout.Memory, true)); } catch { if (peImage != null) peImage.Dispose(); peImage = null; } try { return Load(peImage = new PEImage(addr, ImageLayout.File, true)); } catch { if (peImage != null) peImage.Dispose(); throw; } } /// /// Create a instance /// /// Address of a .NET file in memory /// Image layout of the file in memory /// A new instance internal static MetaData Load(IntPtr addr, ImageLayout imageLayout) { IPEImage peImage = null; try { return Load(peImage = new PEImage(addr, imageLayout, true)); } catch { if (peImage != null) peImage.Dispose(); throw; } } /// /// Create a instance /// /// The PE image /// A new instance internal static MetaData Load(IPEImage peImage) { return Create(peImage, true); } /// /// Create a instance /// /// The PE image /// A new instance public static IMetaData CreateMetaData(IPEImage peImage) { return Create(peImage, true); } /// /// Create a instance /// /// The PE image /// true if we should verify that it's a .NET PE file /// A new instance public static IMetaData CreateMetaData(IPEImage peImage, bool verify) { return Create(peImage, verify); } /// /// Create a instance /// /// The PE image /// true if we should verify that it's a .NET PE file /// A new instance static MetaData Create(IPEImage peImage, bool verify) { IImageStream cor20HeaderStream = null, mdHeaderStream = null; MetaData md = null; try { var dotNetDir = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[14]; if (dotNetDir.VirtualAddress == 0) throw new BadImageFormatException(".NET data directory RVA is 0"); if (dotNetDir.Size < 0x48) throw new BadImageFormatException(".NET data directory size < 0x48"); var cor20Header = new ImageCor20Header(cor20HeaderStream = peImage.CreateStream(dotNetDir.VirtualAddress, 0x48), verify); if (cor20Header.MetaData.VirtualAddress == 0) throw new BadImageFormatException(".NET MetaData RVA is 0"); if (cor20Header.MetaData.Size < 16) throw new BadImageFormatException(".NET MetaData size is too small"); var mdSize = cor20Header.MetaData.Size; var mdRva = cor20Header.MetaData.VirtualAddress; var mdHeader = new MetaDataHeader(mdHeaderStream = peImage.CreateStream(mdRva, mdSize), verify); if (verify) { foreach (var sh in mdHeader.StreamHeaders) { if (sh.Offset + sh.StreamSize < sh.Offset || sh.Offset + sh.StreamSize > mdSize) throw new BadImageFormatException("Invalid stream header"); } } switch (GetMetaDataType(mdHeader.StreamHeaders)) { case MetaDataType.Compressed: md = new CompressedMetaData(peImage, cor20Header, mdHeader); break; case MetaDataType.ENC: md = new ENCMetaData(peImage, cor20Header, mdHeader); break; default: throw new BadImageFormatException("No #~ or #- stream found"); } md.Initialize(null); return md; } catch { if (md != null) md.Dispose(); throw; } finally { if (cor20HeaderStream != null) cor20HeaderStream.Dispose(); if (mdHeaderStream != null) mdHeaderStream.Dispose(); } } /// /// Create a standalone portable PDB instance /// /// Metadata stream /// true if we should verify that it's a .NET PE file /// A new instance internal static MetaData CreateStandalonePortablePDB(IImageStream mdStream, bool verify) { MetaData md = null; try { var mdHeader = new MetaDataHeader(mdStream, verify); if (verify) { foreach (var sh in mdHeader.StreamHeaders) { if (sh.Offset + sh.StreamSize < sh.Offset || sh.Offset + sh.StreamSize > mdStream.Length) throw new BadImageFormatException("Invalid stream header"); } } switch (GetMetaDataType(mdHeader.StreamHeaders)) { case MetaDataType.Compressed: md = new CompressedMetaData(mdHeader, true); break; case MetaDataType.ENC: md = new ENCMetaData(mdHeader, true); break; default: throw new BadImageFormatException("No #~ or #- stream found"); } md.Initialize(mdStream); return md; } catch { if (md != null) md.Dispose(); throw; } } static MetaDataType GetMetaDataType(IList streamHeaders) { MetaDataType? mdType = null; foreach (var sh in streamHeaders) { if (mdType == null) { if (sh.Name == "#~") mdType = MetaDataType.Compressed; else if (sh.Name == "#-") mdType = MetaDataType.ENC; } if (sh.Name == "#Schema") mdType = MetaDataType.ENC; } if (mdType == null) return MetaDataType.Unknown; return mdType.Value; } } } dnlib-2.1_VS2010/src/DotNet/MD/MetaDataHeader.cs000066400000000000000000000100511325033663500207660ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Text; using dnlib.IO; namespace dnlib.DotNet.MD { /// /// Represents the .NET metadata header /// /// IMAGE_COR20_HEADER.MetaData points to this header public sealed class MetaDataHeader : FileSection { readonly uint signature; readonly ushort majorVersion; readonly ushort minorVersion; readonly uint reserved1; readonly uint stringLength; readonly string versionString; readonly FileOffset offset2ndPart; readonly StorageFlags flags; readonly byte reserved2; readonly ushort streams; readonly IList streamHeaders; /// /// Returns the signature (should be 0x424A5342) /// public uint Signature { get { return signature; } } /// /// Returns the major version /// public ushort MajorVersion { get { return majorVersion; } } /// /// Returns the minor version /// public ushort MinorVersion { get { return minorVersion; } } /// /// Returns the reserved dword (pointer to extra header data) /// public uint Reserved1 { get { return reserved1; } } /// /// Returns the version string length value /// public uint StringLength { get { return stringLength; } } /// /// Returns the version string /// public string VersionString { get { return versionString; } } /// /// Returns the offset of STORAGEHEADER /// public FileOffset StorageHeaderOffset { get { return offset2ndPart; } } /// /// Returns the flags (reserved) /// public StorageFlags Flags { get { return flags; } } /// /// Returns the reserved byte (padding) /// public byte Reserved2 { get { return reserved2; } } /// /// Returns the number of streams /// public ushort Streams { get { return streams; } } /// /// Returns all stream headers /// public IList StreamHeaders { get { return streamHeaders; } } /// /// Constructor /// /// PE file reader pointing to the start of this section /// Verify section /// Thrown if verification fails public MetaDataHeader(IImageStream reader, bool verify) { SetStartOffset(reader); this.signature = reader.ReadUInt32(); if (verify && this.signature != 0x424A5342) throw new BadImageFormatException("Invalid MetaData header signature"); this.majorVersion = reader.ReadUInt16(); this.minorVersion = reader.ReadUInt16(); if (verify && !((majorVersion == 1 && minorVersion == 1) || (majorVersion == 0 && minorVersion >= 19))) throw new BadImageFormatException(string.Format("Unknown MetaData header version: {0}.{1}", majorVersion, minorVersion)); this.reserved1 = reader.ReadUInt32(); this.stringLength = reader.ReadUInt32(); this.versionString = ReadString(reader, stringLength); this.offset2ndPart = reader.FileOffset + reader.Position; this.flags = (StorageFlags)reader.ReadByte(); this.reserved2 = reader.ReadByte(); this.streams = reader.ReadUInt16(); this.streamHeaders = new StreamHeader[streams]; for (int i = 0; i < streamHeaders.Count; i++) streamHeaders[i] = new StreamHeader(reader, verify); SetEndoffset(reader); } static string ReadString(IImageStream reader, uint maxLength) { long endPos = reader.Position + maxLength; if (endPos < reader.Position || endPos > reader.Length) throw new BadImageFormatException("Invalid MD version string"); byte[] utf8Bytes = new byte[maxLength]; uint i; for (i = 0; i < maxLength; i++) { byte b = reader.ReadByte(); if (b == 0) break; utf8Bytes[i] = b; } reader.Position = endPos; return Encoding.UTF8.GetString(utf8Bytes, 0, (int)i); } } } dnlib-2.1_VS2010/src/DotNet/MD/PdbStream.cs000066400000000000000000000024071325033663500200640ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.IO; namespace dnlib.DotNet.MD { /// /// #Pdb stream /// public sealed class PdbStream : HeapStream { /// /// Gets the PDB id /// public byte[] Id { get; private set; } /// /// Gets the entry point token or 0 /// public MDToken EntryPoint { get; private set; } /// /// Gets the referenced type system tables in the PE metadata file /// public ulong ReferencedTypeSystemTables { get; private set; } /// /// Gets all type system table rows. This array has exactly 64 elements. /// public uint[] TypeSystemTableRows { get; private set; } /// public PdbStream(IImageStream imageStream, StreamHeader streamHeader) : base(imageStream, streamHeader) { using (var stream = GetClonedImageStream()) { Id = stream.ReadBytes(20); EntryPoint = new MDToken(stream.ReadUInt32()); var tables = stream.ReadUInt64(); ReferencedTypeSystemTables = tables; var rows = new uint[64]; for (int i = 0; i < rows.Length; i++, tables >>= 1) { if (((uint)tables & 1) != 0) rows[i] = stream.ReadUInt32(); } TypeSystemTableRows = rows; } } } } dnlib-2.1_VS2010/src/DotNet/MD/RawRowEqualityComparer.cs000066400000000000000000000444111325033663500226340ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; #pragma warning disable 1591 // XML doc comments namespace dnlib.DotNet.MD { /// /// Equality comparer for all raw rows /// public sealed class RawRowEqualityComparer : IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer { /// /// Default instance /// public static readonly RawRowEqualityComparer Instance = new RawRowEqualityComparer(); static int rol(uint val, int shift) { return (int)((val << shift) | (val >> (32 - shift))); } public bool Equals(RawModuleRow x, RawModuleRow y) { return x.Generation == y.Generation && x.Name == y.Name && x.Mvid == y.Mvid && x.EncId == y.EncId && x.EncBaseId == y.EncBaseId; } public int GetHashCode(RawModuleRow obj) { return obj.Generation + rol(obj.Name, 3) + rol(obj.Mvid, 7) + rol(obj.EncId, 11) + rol(obj.EncBaseId, 15); } public bool Equals(RawTypeRefRow x, RawTypeRefRow y) { return x.ResolutionScope == y.ResolutionScope && x.Name == y.Name && x.Namespace == y.Namespace; } public int GetHashCode(RawTypeRefRow obj) { return (int)obj.ResolutionScope + rol(obj.Name, 3) + rol(obj.Namespace, 7); } public bool Equals(RawTypeDefRow x, RawTypeDefRow y) { return x.Flags == y.Flags && x.Name == y.Name && x.Namespace == y.Namespace && x.Extends == y.Extends && x.FieldList == y.FieldList && x.MethodList == y.MethodList; } public int GetHashCode(RawTypeDefRow obj) { return (int)obj.Flags + rol(obj.Name, 3) + rol(obj.Namespace, 7) + rol(obj.Extends, 11) + rol(obj.FieldList, 15) + rol(obj.MethodList, 19); } public bool Equals(RawFieldPtrRow x, RawFieldPtrRow y) { return x.Field == y.Field; } public int GetHashCode(RawFieldPtrRow obj) { return (int)obj.Field; } public bool Equals(RawFieldRow x, RawFieldRow y) { return x.Flags == y.Flags && x.Name == y.Name && x.Signature == y.Signature; } public int GetHashCode(RawFieldRow obj) { return (int)obj.Flags + rol(obj.Name, 3) + rol(obj.Signature, 7); } public bool Equals(RawMethodPtrRow x, RawMethodPtrRow y) { return x.Method == y.Method; } public int GetHashCode(RawMethodPtrRow obj) { return (int)obj.Method; } public bool Equals(RawMethodRow x, RawMethodRow y) { return x.RVA == y.RVA && x.ImplFlags == y.ImplFlags && x.Flags == y.Flags && x.Name == y.Name && x.Signature == y.Signature && x.ParamList == y.ParamList; } public int GetHashCode(RawMethodRow obj) { return (int)obj.RVA + rol(obj.ImplFlags, 3) + rol(obj.Flags, 7) + rol(obj.Name, 11) + rol(obj.Signature, 15) + rol(obj.ParamList, 19); } public bool Equals(RawParamPtrRow x, RawParamPtrRow y) { return x.Param == y.Param; } public int GetHashCode(RawParamPtrRow obj) { return (int)obj.Param; } public bool Equals(RawParamRow x, RawParamRow y) { return x.Flags == y.Flags && x.Sequence == y.Sequence && x.Name == y.Name; } public int GetHashCode(RawParamRow obj) { return (int)obj.Flags + rol(obj.Sequence, 3) + rol(obj.Name, 7); } public bool Equals(RawInterfaceImplRow x, RawInterfaceImplRow y) { return x.Class == y.Class && x.Interface == y.Interface; } public int GetHashCode(RawInterfaceImplRow obj) { return (int)obj.Class + rol(obj.Interface, 3); } public bool Equals(RawMemberRefRow x, RawMemberRefRow y) { return x.Class == y.Class && x.Name == y.Name && x.Signature == y.Signature; } public int GetHashCode(RawMemberRefRow obj) { return (int)obj.Class + rol(obj.Name, 3) + rol(obj.Signature, 7); } public bool Equals(RawConstantRow x, RawConstantRow y) { return x.Type == y.Type && x.Padding == y.Padding && x.Parent == y.Parent && x.Value == y.Value; } public int GetHashCode(RawConstantRow obj) { return (int)obj.Type + rol(obj.Padding, 3) + rol(obj.Parent, 7) + rol(obj.Value, 11); } public bool Equals(RawCustomAttributeRow x, RawCustomAttributeRow y) { return x.Parent == y.Parent && x.Type == y.Type && x.Value == y.Value; } public int GetHashCode(RawCustomAttributeRow obj) { return (int)obj.Parent + rol(obj.Type, 3) + rol(obj.Value, 7); } public bool Equals(RawFieldMarshalRow x, RawFieldMarshalRow y) { return x.Parent == y.Parent && x.NativeType == y.NativeType; } public int GetHashCode(RawFieldMarshalRow obj) { return (int)obj.Parent + rol(obj.NativeType, 3); } public bool Equals(RawDeclSecurityRow x, RawDeclSecurityRow y) { return x.Action == y.Action && x.Parent == y.Parent && x.PermissionSet == y.PermissionSet; } public int GetHashCode(RawDeclSecurityRow obj) { return (int)obj.Action + rol(obj.Parent, 3) + rol(obj.PermissionSet, 7); } public bool Equals(RawClassLayoutRow x, RawClassLayoutRow y) { return x.PackingSize == y.PackingSize && x.ClassSize == y.ClassSize && x.Parent == y.Parent; } public int GetHashCode(RawClassLayoutRow obj) { return (int)obj.PackingSize + rol(obj.ClassSize, 3) + rol(obj.Parent, 7); } public bool Equals(RawFieldLayoutRow x, RawFieldLayoutRow y) { return x.OffSet == y.OffSet && x.Field == y.Field; } public int GetHashCode(RawFieldLayoutRow obj) { return (int)obj.OffSet + rol(obj.Field, 3); } public bool Equals(RawStandAloneSigRow x, RawStandAloneSigRow y) { return x.Signature == y.Signature; } public int GetHashCode(RawStandAloneSigRow obj) { return (int)obj.Signature; } public bool Equals(RawEventMapRow x, RawEventMapRow y) { return x.Parent == y.Parent && x.EventList == y.EventList; } public int GetHashCode(RawEventMapRow obj) { return (int)obj.Parent + rol(obj.EventList, 3); } public bool Equals(RawEventPtrRow x, RawEventPtrRow y) { return x.Event == y.Event; } public int GetHashCode(RawEventPtrRow obj) { return (int)obj.Event; } public bool Equals(RawEventRow x, RawEventRow y) { return x.EventFlags == y.EventFlags && x.Name == y.Name && x.EventType == y.EventType; } public int GetHashCode(RawEventRow obj) { return (int)obj.EventFlags + rol(obj.Name, 3) + rol(obj.EventType, 7); } public bool Equals(RawPropertyMapRow x, RawPropertyMapRow y) { return x.Parent == y.Parent && x.PropertyList == y.PropertyList; } public int GetHashCode(RawPropertyMapRow obj) { return (int)obj.Parent + rol(obj.PropertyList, 3); } public bool Equals(RawPropertyPtrRow x, RawPropertyPtrRow y) { return x.Property == y.Property; } public int GetHashCode(RawPropertyPtrRow obj) { return (int)obj.Property; } public bool Equals(RawPropertyRow x, RawPropertyRow y) { return x.PropFlags == y.PropFlags && x.Name == y.Name && x.Type == y.Type; } public int GetHashCode(RawPropertyRow obj) { return (int)obj.PropFlags + rol(obj.Name, 3) + rol(obj.Type, 7); } public bool Equals(RawMethodSemanticsRow x, RawMethodSemanticsRow y) { return x.Semantic == y.Semantic && x.Method == y.Method && x.Association == y.Association; } public int GetHashCode(RawMethodSemanticsRow obj) { return (int)obj.Semantic + rol(obj.Method, 3) + rol(obj.Association, 7); } public bool Equals(RawMethodImplRow x, RawMethodImplRow y) { return x.Class == y.Class && x.MethodBody == y.MethodBody && x.MethodDeclaration == y.MethodDeclaration; } public int GetHashCode(RawMethodImplRow obj) { return (int)obj.Class + rol(obj.MethodBody, 3) + rol(obj.MethodDeclaration, 7); } public bool Equals(RawModuleRefRow x, RawModuleRefRow y) { return x.Name == y.Name; } public int GetHashCode(RawModuleRefRow obj) { return (int)obj.Name; } public bool Equals(RawTypeSpecRow x, RawTypeSpecRow y) { return x.Signature == y.Signature; } public int GetHashCode(RawTypeSpecRow obj) { return (int)obj.Signature; } public bool Equals(RawImplMapRow x, RawImplMapRow y) { return x.MappingFlags == y.MappingFlags && x.MemberForwarded == y.MemberForwarded && x.ImportName == y.ImportName && x.ImportScope == y.ImportScope; } public int GetHashCode(RawImplMapRow obj) { return (int)obj.MappingFlags + rol(obj.MemberForwarded, 3) + rol(obj.ImportName, 7) + rol(obj.ImportScope, 11); } public bool Equals(RawFieldRVARow x, RawFieldRVARow y) { return x.RVA == y.RVA && x.Field == y.Field; } public int GetHashCode(RawFieldRVARow obj) { return (int)obj.RVA + rol(obj.Field, 3); } public bool Equals(RawENCLogRow x, RawENCLogRow y) { return x.Token == y.Token && x.FuncCode == y.FuncCode; } public int GetHashCode(RawENCLogRow obj) { return (int)obj.Token + rol(obj.FuncCode, 3); } public bool Equals(RawENCMapRow x, RawENCMapRow y) { return x.Token == y.Token; } public int GetHashCode(RawENCMapRow obj) { return (int)obj.Token; } public bool Equals(RawAssemblyRow x, RawAssemblyRow y) { return x.HashAlgId == y.HashAlgId && x.MajorVersion == y.MajorVersion && x.MinorVersion == y.MinorVersion && x.BuildNumber == y.BuildNumber && x.RevisionNumber == y.RevisionNumber && x.Flags == y.Flags && x.PublicKey == y.PublicKey && x.Name == y.Name && x.Locale == y.Locale; } public int GetHashCode(RawAssemblyRow obj) { return (int)obj.HashAlgId + rol(obj.MajorVersion, 3) + rol(obj.MinorVersion, 7) + rol(obj.BuildNumber, 11) + rol(obj.RevisionNumber, 15) + rol(obj.Flags, 19) + rol(obj.PublicKey, 23) + rol(obj.Name, 27) + rol(obj.Locale, 31); } public bool Equals(RawAssemblyProcessorRow x, RawAssemblyProcessorRow y) { return x.Processor == y.Processor; } public int GetHashCode(RawAssemblyProcessorRow obj) { return (int)obj.Processor; } public bool Equals(RawAssemblyOSRow x, RawAssemblyOSRow y) { return x.OSPlatformId == y.OSPlatformId && x.OSMajorVersion == y.OSMajorVersion && x.OSMinorVersion == y.OSMinorVersion; } public int GetHashCode(RawAssemblyOSRow obj) { return (int)obj.OSPlatformId + rol(obj.OSMajorVersion, 3) + rol(obj.OSMinorVersion, 7); } public bool Equals(RawAssemblyRefRow x, RawAssemblyRefRow y) { return x.MajorVersion == y.MajorVersion && x.MinorVersion == y.MinorVersion && x.BuildNumber == y.BuildNumber && x.RevisionNumber == y.RevisionNumber && x.Flags == y.Flags && x.PublicKeyOrToken == y.PublicKeyOrToken && x.Name == y.Name && x.Locale == y.Locale && x.HashValue == y.HashValue; } public int GetHashCode(RawAssemblyRefRow obj) { return (int)obj.MajorVersion + rol(obj.MinorVersion, 3) + rol(obj.BuildNumber, 7) + rol(obj.RevisionNumber, 11) + rol(obj.Flags, 15) + rol(obj.PublicKeyOrToken, 19) + rol(obj.Name, 23) + rol(obj.Locale, 27) + rol(obj.HashValue, 31); } public bool Equals(RawAssemblyRefProcessorRow x, RawAssemblyRefProcessorRow y) { return x.Processor == y.Processor && x.AssemblyRef == y.AssemblyRef; } public int GetHashCode(RawAssemblyRefProcessorRow obj) { return (int)obj.Processor + rol(obj.AssemblyRef, 3); } public bool Equals(RawAssemblyRefOSRow x, RawAssemblyRefOSRow y) { return x.OSPlatformId == y.OSPlatformId && x.OSMajorVersion == y.OSMajorVersion && x.OSMinorVersion == y.OSMinorVersion && x.AssemblyRef == y.AssemblyRef; } public int GetHashCode(RawAssemblyRefOSRow obj) { return (int)obj.OSPlatformId + rol(obj.OSMajorVersion, 3) + rol(obj.OSMinorVersion, 7) + rol(obj.AssemblyRef, 11); } public bool Equals(RawFileRow x, RawFileRow y) { return x.Flags == y.Flags && x.Name == y.Name && x.HashValue == y.HashValue; } public int GetHashCode(RawFileRow obj) { return (int)obj.Flags + rol(obj.Name, 3) + rol(obj.HashValue, 7); } public bool Equals(RawExportedTypeRow x, RawExportedTypeRow y) { return x.Flags == y.Flags && x.TypeDefId == y.TypeDefId && x.TypeName == y.TypeName && x.TypeNamespace == y.TypeNamespace && x.Implementation == y.Implementation; } public int GetHashCode(RawExportedTypeRow obj) { return (int)obj.Flags + rol(obj.TypeDefId, 3) + rol(obj.TypeName, 7) + rol(obj.TypeNamespace, 11) + rol(obj.Implementation, 15); } public bool Equals(RawManifestResourceRow x, RawManifestResourceRow y) { return x.Offset == y.Offset && x.Flags == y.Flags && x.Name == y.Name && x.Implementation == y.Implementation; } public int GetHashCode(RawManifestResourceRow obj) { return (int)obj.Offset + rol(obj.Flags, 3) + rol(obj.Name, 7) + rol(obj.Implementation, 11); } public bool Equals(RawNestedClassRow x, RawNestedClassRow y) { return x.NestedClass == y.NestedClass && x.EnclosingClass == y.EnclosingClass; } public int GetHashCode(RawNestedClassRow obj) { return (int)obj.NestedClass + rol(obj.EnclosingClass, 3); } public bool Equals(RawGenericParamRow x, RawGenericParamRow y) { return x.Number == y.Number && x.Flags == y.Flags && x.Owner == y.Owner && x.Name == y.Name && x.Kind == y.Kind; } public int GetHashCode(RawGenericParamRow obj) { return (int)obj.Number + rol(obj.Flags, 3) + rol(obj.Owner, 7) + rol(obj.Name, 11) + rol(obj.Kind, 15); } public bool Equals(RawMethodSpecRow x, RawMethodSpecRow y) { return x.Method == y.Method && x.Instantiation == y.Instantiation; } public int GetHashCode(RawMethodSpecRow obj) { return (int)obj.Method + rol(obj.Instantiation, 3); } public bool Equals(RawGenericParamConstraintRow x, RawGenericParamConstraintRow y) { return x.Owner == y.Owner && x.Constraint == y.Constraint; } public int GetHashCode(RawGenericParamConstraintRow obj) { return (int)obj.Owner + rol(obj.Constraint, 3); } public bool Equals(RawDocumentRow x, RawDocumentRow y) { return x.Name == y.Name && x.HashAlgorithm == y.HashAlgorithm && x.Hash == y.Hash && x.Language == y.Language; } public int GetHashCode(RawDocumentRow obj) { return (int)obj.Name + rol(obj.HashAlgorithm, 3) + rol(obj.Hash, 7) + rol(obj.Language, 11); } public bool Equals(RawMethodDebugInformationRow x, RawMethodDebugInformationRow y) { return x.Document == y.Document && x.SequencePoints == y.SequencePoints; } public int GetHashCode(RawMethodDebugInformationRow obj) { return (int)obj.Document + rol(obj.SequencePoints, 3); } public bool Equals(RawLocalScopeRow x, RawLocalScopeRow y) { return x.Method == y.Method && x.ImportScope == y.ImportScope && x.VariableList == y.VariableList && x.ConstantList == y.ConstantList && x.StartOffset == y.StartOffset && x.Length == y.Length; } public int GetHashCode(RawLocalScopeRow obj) { return (int)obj.Method + rol(obj.ImportScope, 3) + rol(obj.VariableList, 7) + rol(obj.ConstantList, 11) + rol(obj.StartOffset, 15) + rol(obj.Length, 19); } public bool Equals(RawLocalVariableRow x, RawLocalVariableRow y) { return x.Attributes == y.Attributes && x.Index == y.Index && x.Name == y.Name; } public int GetHashCode(RawLocalVariableRow obj) { return obj.Attributes + rol(obj.Index, 3) + rol(obj.Name, 7); } public bool Equals(RawLocalConstantRow x, RawLocalConstantRow y) { return x.Name == y.Name && x.Signature == y.Signature; } public int GetHashCode(RawLocalConstantRow obj) { return (int)obj.Name + rol(obj.Signature, 3); } public bool Equals(RawImportScopeRow x, RawImportScopeRow y) { return x.Parent == y.Parent && x.Imports == y.Imports; } public int GetHashCode(RawImportScopeRow obj) { return (int)obj.Parent + rol(obj.Imports, 3); } public bool Equals(RawStateMachineMethodRow x, RawStateMachineMethodRow y) { return x.MoveNextMethod == y.MoveNextMethod && x.KickoffMethod == y.KickoffMethod; } public int GetHashCode(RawStateMachineMethodRow obj) { return (int)obj.MoveNextMethod + rol(obj.KickoffMethod, 3); } public bool Equals(RawCustomDebugInformationRow x, RawCustomDebugInformationRow y) { return x.Parent == y.Parent && x.Kind == y.Kind && x.Value == y.Value; } public int GetHashCode(RawCustomDebugInformationRow obj) { return (int)obj.Parent + rol(obj.Kind, 3) + rol(obj.Value, 7); } } } dnlib-2.1_VS2010/src/DotNet/MD/RawTableRows.cs000066400000000000000000001444471325033663500205720ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.MD { /// /// A raw table row /// public interface IRawRow { /// /// Reads a column /// /// Column index /// Column value uint Read(int index); /// /// Writes a column /// /// Column index /// New value void Write(int index, uint value); } /// /// Raw contents of an uncompressed Module table row /// public sealed class RawModuleRow : IRawRow { /// public ushort Generation; /// public uint Name; /// public uint Mvid; /// public uint EncId; /// public uint EncBaseId; /// Default constructor public RawModuleRow() { } /// Constructor public RawModuleRow(ushort Generation, uint Name, uint Mvid, uint EncId, uint EncBaseId) { this.Generation = Generation; this.Name = Name; this.Mvid = Mvid; this.EncId = EncId; this.EncBaseId = EncBaseId; } /// public uint Read(int index) { switch (index) { case 0: return Generation; case 1: return Name; case 2: return Mvid; case 3: return EncId; case 4: return EncBaseId; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Generation = (ushort)value; break; case 1: Name = value; break; case 2: Mvid = value; break; case 3: EncId = value; break; case 4: EncBaseId = value; break; default: break; } } } /// /// Raw contents of an uncompressed TypeRef table row /// public sealed class RawTypeRefRow : IRawRow { /// public uint ResolutionScope; /// public uint Name; /// public uint Namespace; /// Default constructor public RawTypeRefRow() { } /// Constructor public RawTypeRefRow(uint ResolutionScope, uint Name, uint Namespace) { this.ResolutionScope = ResolutionScope; this.Name = Name; this.Namespace = Namespace; } /// public uint Read(int index) { switch (index) { case 0: return ResolutionScope; case 1: return Name; case 2: return Namespace; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: ResolutionScope = value; break; case 1: Name = value; break; case 2: Namespace = value; break; default: break; } } } /// /// Raw contents of an uncompressed TypeDef table row /// public sealed class RawTypeDefRow : IRawRow { /// public uint Flags; /// public uint Name; /// public uint Namespace; /// public uint Extends; /// public uint FieldList; /// public uint MethodList; /// Default constructor public RawTypeDefRow() { } /// Constructor public RawTypeDefRow(uint Flags, uint Name, uint Namespace, uint Extends, uint FieldList, uint MethodList) { this.Flags = Flags; this.Name = Name; this.Namespace = Namespace; this.Extends = Extends; this.FieldList = FieldList; this.MethodList = MethodList; } /// public uint Read(int index) { switch (index) { case 0: return Flags; case 1: return Name; case 2: return Namespace; case 3: return Extends; case 4: return FieldList; case 5: return MethodList; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Flags = value; break; case 1: Name = value; break; case 2: Namespace = value; break; case 3: Extends = value; break; case 4: FieldList = value; break; case 5: MethodList = value; break; default: break; } } } /// /// Raw contents of an uncompressed FieldPtr table row /// public sealed class RawFieldPtrRow : IRawRow { /// public uint Field; /// Default constructor public RawFieldPtrRow() { } /// Constructor public RawFieldPtrRow(uint Field) { this.Field = Field; } /// public uint Read(int index) { switch (index) { case 0: return Field; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Field = value; break; default: break; } } } /// /// Raw contents of an uncompressed Field table row /// public sealed class RawFieldRow : IRawRow { /// public ushort Flags; /// public uint Name; /// public uint Signature; /// Default constructor public RawFieldRow() { } /// Constructor public RawFieldRow(ushort Flags, uint Name, uint Signature) { this.Flags = Flags; this.Name = Name; this.Signature = Signature; } /// public uint Read(int index) { switch (index) { case 0: return Flags; case 1: return Name; case 2: return Signature; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Flags = (ushort)value; break; case 1: Name = value; break; case 2: Signature = value; break; default: break; } } } /// /// Raw contents of an uncompressed MethodPtr table row /// public sealed class RawMethodPtrRow : IRawRow { /// public uint Method; /// Default constructor public RawMethodPtrRow() { } /// Constructor public RawMethodPtrRow(uint Method) { this.Method = Method; } /// public uint Read(int index) { switch (index) { case 0: return Method; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Method = value; break; default: break; } } } /// /// Raw contents of an uncompressed Method table row /// public sealed class RawMethodRow : IRawRow { /// public uint RVA; /// public ushort ImplFlags; /// public ushort Flags; /// public uint Name; /// public uint Signature; /// public uint ParamList; /// Default constructor public RawMethodRow() { } /// Constructor public RawMethodRow(uint RVA, ushort ImplFlags, ushort Flags, uint Name, uint Signature, uint ParamList) { this.RVA = RVA; this.ImplFlags = ImplFlags; this.Flags = Flags; this.Name = Name; this.Signature = Signature; this.ParamList = ParamList; } /// public uint Read(int index) { switch (index) { case 0: return RVA; case 1: return ImplFlags; case 2: return Flags; case 3: return Name; case 4: return Signature; case 5: return ParamList; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: RVA = value; break; case 1: ImplFlags = (ushort)value; break; case 2: Flags = (ushort)value; break; case 3: Name = value; break; case 4: Signature = value; break; case 5: ParamList = value; break; default: break; } } } /// /// Raw contents of an uncompressed ParamPtr table row /// public sealed class RawParamPtrRow : IRawRow { /// public uint Param; /// Default constructor public RawParamPtrRow() { } /// Constructor public RawParamPtrRow(uint Param) { this.Param = Param; } /// public uint Read(int index) { switch (index) { case 0: return Param; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Param = value; break; default: break; } } } /// /// Raw contents of an uncompressed Param table row /// public sealed class RawParamRow : IRawRow { /// public ushort Flags; /// public ushort Sequence; /// public uint Name; /// Default constructor public RawParamRow() { } /// Constructor public RawParamRow(ushort Flags, ushort Sequence, uint Name) { this.Flags = Flags; this.Sequence = Sequence; this.Name = Name; } /// public uint Read(int index) { switch (index) { case 0: return Flags; case 1: return Sequence; case 2: return Name; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Flags = (ushort)value; break; case 1: Sequence = (ushort)value; break; case 2: Name = value; break; default: break; } } } /// /// Raw contents of an uncompressed InterfaceImpl table row /// public sealed class RawInterfaceImplRow : IRawRow { /// public uint Class; /// public uint Interface; /// Default constructor public RawInterfaceImplRow() { } /// Constructor public RawInterfaceImplRow(uint Class, uint Interface) { this.Class = Class; this.Interface = Interface; } /// public uint Read(int index) { switch (index) { case 0: return Class; case 1: return Interface; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Class = value; break; case 1: Interface = value; break; default: break; } } } /// /// Raw contents of an uncompressed MemberRef table row /// public sealed class RawMemberRefRow : IRawRow { /// public uint Class; /// public uint Name; /// public uint Signature; /// Default constructor public RawMemberRefRow() { } /// Constructor public RawMemberRefRow(uint Class, uint Name, uint Signature) { this.Class = Class; this.Name = Name; this.Signature = Signature; } /// public uint Read(int index) { switch (index) { case 0: return Class; case 1: return Name; case 2: return Signature; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Class = value; break; case 1: Name = value; break; case 2: Signature = value; break; default: break; } } } /// /// Raw contents of an uncompressed Constant table row /// public sealed class RawConstantRow : IRawRow { /// public byte Type; /// public byte Padding; /// public uint Parent; /// public uint Value; /// Default constructor public RawConstantRow() { } /// Constructor public RawConstantRow(byte Type, byte Padding, uint Parent, uint Value) { this.Type = Type; this.Padding = Padding; this.Parent = Parent; this.Value = Value; } /// public uint Read(int index) { switch (index) { case 0: return Type; case 1: return Padding; case 2: return Parent; case 3: return Value; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Type = (byte)value; break; case 1: Padding = (byte)value; break; case 2: Parent = value; break; case 3: Value = value; break; default: break; } } } /// /// Raw contents of an uncompressed CustomAttribute table row /// public sealed class RawCustomAttributeRow : IRawRow { /// public uint Parent; /// public uint Type; /// public uint Value; /// Default constructor public RawCustomAttributeRow() { } /// Constructor public RawCustomAttributeRow(uint Parent, uint Type, uint Value) { this.Parent = Parent; this.Type = Type; this.Value = Value; } /// public uint Read(int index) { switch (index) { case 0: return Parent; case 1: return Type; case 2: return Value; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Parent = value; break; case 1: Type = value; break; case 2: Value = value; break; default: break; } } } /// /// Raw contents of an uncompressed FieldMarshal table row /// public sealed class RawFieldMarshalRow : IRawRow { /// public uint Parent; /// public uint NativeType; /// Default constructor public RawFieldMarshalRow() { } /// Constructor public RawFieldMarshalRow(uint Parent, uint NativeType) { this.Parent = Parent; this.NativeType = NativeType; } /// public uint Read(int index) { switch (index) { case 0: return Parent; case 1: return NativeType; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Parent = value; break; case 1: NativeType = value; break; default: break; } } } /// /// Raw contents of an uncompressed DeclSecurity table row /// public sealed class RawDeclSecurityRow : IRawRow { /// public short Action; /// public uint Parent; /// public uint PermissionSet; /// Default constructor public RawDeclSecurityRow() { } /// Constructor public RawDeclSecurityRow(short Action, uint Parent, uint PermissionSet) { this.Action = Action; this.Parent = Parent; this.PermissionSet = PermissionSet; } /// public uint Read(int index) { switch (index) { case 0: return (uint)(int)Action; case 1: return Parent; case 2: return PermissionSet; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Action = (short)value; break; case 1: Parent = value; break; case 2: PermissionSet = value; break; default: break; } } } /// /// Raw contents of an uncompressed ClassLayout table row /// public sealed class RawClassLayoutRow : IRawRow { /// public ushort PackingSize; /// public uint ClassSize; /// public uint Parent; /// Default constructor public RawClassLayoutRow() { } /// Constructor public RawClassLayoutRow(ushort PackingSize, uint ClassSize, uint Parent) { this.PackingSize = PackingSize; this.ClassSize = ClassSize; this.Parent = Parent; } /// public uint Read(int index) { switch (index) { case 0: return PackingSize; case 1: return ClassSize; case 2: return Parent; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: PackingSize = (ushort)value; break; case 1: ClassSize = value; break; case 2: Parent = value; break; default: break; } } } /// /// Raw contents of an uncompressed FieldLayout table row /// public sealed class RawFieldLayoutRow : IRawRow { /// public uint OffSet; /// public uint Field; /// Default constructor public RawFieldLayoutRow() { } /// Constructor public RawFieldLayoutRow(uint OffSet, uint Field) { this.OffSet = OffSet; this.Field = Field; } /// public uint Read(int index) { switch (index) { case 0: return OffSet; case 1: return Field; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: OffSet = value; break; case 1: Field = value; break; default: break; } } } /// /// Raw contents of an uncompressed StandAloneSig table row /// public sealed class RawStandAloneSigRow : IRawRow { /// public uint Signature; /// Default constructor public RawStandAloneSigRow() { } /// Constructor public RawStandAloneSigRow(uint Signature) { this.Signature = Signature; } /// public uint Read(int index) { switch (index) { case 0: return Signature; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Signature = value; break; default: break; } } } /// /// Raw contents of an uncompressed EventMap table row /// public sealed class RawEventMapRow : IRawRow { /// public uint Parent; /// public uint EventList; /// Default constructor public RawEventMapRow() { } /// Constructor public RawEventMapRow(uint Parent, uint EventList) { this.Parent = Parent; this.EventList = EventList; } /// public uint Read(int index) { switch (index) { case 0: return Parent; case 1: return EventList; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Parent = value; break; case 1: EventList = value; break; default: break; } } } /// /// Raw contents of an uncompressed EventPtr table row /// public sealed class RawEventPtrRow : IRawRow { /// public uint Event; /// Default constructor public RawEventPtrRow() { } /// Constructor public RawEventPtrRow(uint Event) { this.Event = Event; } /// public uint Read(int index) { switch (index) { case 0: return Event; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Event = value; break; default: break; } } } /// /// Raw contents of an uncompressed Event table row /// public sealed class RawEventRow : IRawRow { /// public ushort EventFlags; /// public uint Name; /// public uint EventType; /// Default constructor public RawEventRow() { } /// Constructor public RawEventRow(ushort EventFlags, uint Name, uint EventType) { this.EventFlags = EventFlags; this.Name = Name; this.EventType = EventType; } /// public uint Read(int index) { switch (index) { case 0: return EventFlags; case 1: return Name; case 2: return EventType; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: EventFlags = (ushort)value; break; case 1: Name = value; break; case 2: EventType = value; break; default: break; } } } /// /// Raw contents of an uncompressed PropertyMap table row /// public sealed class RawPropertyMapRow : IRawRow { /// public uint Parent; /// public uint PropertyList; /// Default constructor public RawPropertyMapRow() { } /// Constructor public RawPropertyMapRow(uint Parent, uint PropertyList) { this.Parent = Parent; this.PropertyList = PropertyList; } /// public uint Read(int index) { switch (index) { case 0: return Parent; case 1: return PropertyList; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Parent = value; break; case 1: PropertyList = value; break; default: break; } } } /// /// Raw contents of an uncompressed PropertyPtr table row /// public sealed class RawPropertyPtrRow : IRawRow { /// public uint Property; /// Default constructor public RawPropertyPtrRow() { } /// Constructor public RawPropertyPtrRow(uint Property) { this.Property = Property; } /// public uint Read(int index) { switch (index) { case 0: return Property; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Property = value; break; default: break; } } } /// /// Raw contents of an uncompressed Property table row /// public sealed class RawPropertyRow : IRawRow { /// public ushort PropFlags; /// public uint Name; /// public uint Type; /// Default constructor public RawPropertyRow() { } /// Constructor public RawPropertyRow(ushort PropFlags, uint Name, uint Type) { this.PropFlags = PropFlags; this.Name = Name; this.Type = Type; } /// public uint Read(int index) { switch (index) { case 0: return PropFlags; case 1: return Name; case 2: return Type; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: PropFlags = (ushort)value; break; case 1: Name = value; break; case 2: Type = value; break; default: break; } } } /// /// Raw contents of an uncompressed MethodSemantics table row /// public sealed class RawMethodSemanticsRow : IRawRow { /// public ushort Semantic; /// public uint Method; /// public uint Association; /// Default constructor public RawMethodSemanticsRow() { } /// Constructor public RawMethodSemanticsRow(ushort Semantic, uint Method, uint Association) { this.Semantic = Semantic; this.Method = Method; this.Association = Association; } /// public uint Read(int index) { switch (index) { case 0: return Semantic; case 1: return Method; case 2: return Association; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Semantic = (ushort)value; break; case 1: Method = value; break; case 2: Association = value; break; default: break; } } } /// /// Raw contents of an uncompressed MethodImpl table row /// public sealed class RawMethodImplRow : IRawRow { /// public uint Class; /// public uint MethodBody; /// public uint MethodDeclaration; /// Default constructor public RawMethodImplRow() { } /// Constructor public RawMethodImplRow(uint Class, uint MethodBody, uint MethodDeclaration) { this.Class = Class; this.MethodBody = MethodBody; this.MethodDeclaration = MethodDeclaration; } /// public uint Read(int index) { switch (index) { case 0: return Class; case 1: return MethodBody; case 2: return MethodDeclaration; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Class = value; break; case 1: MethodBody = value; break; case 2: MethodDeclaration = value; break; default: break; } } } /// /// Raw contents of an uncompressed ModuleRef table row /// public sealed class RawModuleRefRow : IRawRow { /// public uint Name; /// Default constructor public RawModuleRefRow() { } /// Constructor public RawModuleRefRow(uint Name) { this.Name = Name; } /// public uint Read(int index) { switch (index) { case 0: return Name; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Name = value; break; default: break; } } } /// /// Raw contents of an uncompressed TypeSpec table row /// public sealed class RawTypeSpecRow : IRawRow { /// public uint Signature; /// Default constructor public RawTypeSpecRow() { } /// Constructor public RawTypeSpecRow(uint Signature) { this.Signature = Signature; } /// public uint Read(int index) { switch (index) { case 0: return Signature; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Signature = value; break; default: break; } } } /// /// Raw contents of an uncompressed ImplMap table row /// public sealed class RawImplMapRow : IRawRow { /// public ushort MappingFlags; /// public uint MemberForwarded; /// public uint ImportName; /// public uint ImportScope; /// Default constructor public RawImplMapRow() { } /// Constructor public RawImplMapRow(ushort MappingFlags, uint MemberForwarded, uint ImportName, uint ImportScope) { this.MappingFlags = MappingFlags; this.MemberForwarded = MemberForwarded; this.ImportName = ImportName; this.ImportScope = ImportScope; } /// public uint Read(int index) { switch (index) { case 0: return MappingFlags; case 1: return MemberForwarded; case 2: return ImportName; case 3: return ImportScope; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: MappingFlags = (ushort)value; break; case 1: MemberForwarded = value; break; case 2: ImportName = value; break; case 3: ImportScope = value; break; default: break; } } } /// /// Raw contents of an uncompressed FieldRVA table row /// public sealed class RawFieldRVARow : IRawRow { /// public uint RVA; /// public uint Field; /// Default constructor public RawFieldRVARow() { } /// Constructor public RawFieldRVARow(uint RVA, uint Field) { this.RVA = RVA; this.Field = Field; } /// public uint Read(int index) { switch (index) { case 0: return RVA; case 1: return Field; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: RVA = value; break; case 1: Field = value; break; default: break; } } } /// /// Raw contents of an uncompressed ENCLog table row /// public sealed class RawENCLogRow : IRawRow { /// public uint Token; /// public uint FuncCode; /// Default constructor public RawENCLogRow() { } /// Constructor public RawENCLogRow(uint Token, uint FuncCode) { this.Token = Token; this.FuncCode = FuncCode; } /// public uint Read(int index) { switch (index) { case 0: return Token; case 1: return FuncCode; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Token = value; break; case 1: FuncCode = value; break; default: break; } } } /// /// Raw contents of an uncompressed ENCMap table row /// public sealed class RawENCMapRow : IRawRow { /// public uint Token; /// Default constructor public RawENCMapRow() { } /// Constructor public RawENCMapRow(uint Token) { this.Token = Token; } /// public uint Read(int index) { switch (index) { case 0: return Token; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Token = value; break; default: break; } } } /// /// Raw contents of an uncompressed Assembly table row /// public sealed class RawAssemblyRow : IRawRow { /// public uint HashAlgId; /// public ushort MajorVersion; /// public ushort MinorVersion; /// public ushort BuildNumber; /// public ushort RevisionNumber; /// public uint Flags; /// public uint PublicKey; /// public uint Name; /// public uint Locale; /// Default constructor public RawAssemblyRow() { } /// Constructor public RawAssemblyRow(uint HashAlgId, ushort MajorVersion, ushort MinorVersion, ushort BuildNumber, ushort RevisionNumber, uint Flags, uint PublicKey, uint Name, uint Locale) { this.HashAlgId = HashAlgId; this.MajorVersion = MajorVersion; this.MinorVersion = MinorVersion; this.BuildNumber = BuildNumber; this.RevisionNumber = RevisionNumber; this.Flags = Flags; this.PublicKey = PublicKey; this.Name = Name; this.Locale = Locale; } /// public uint Read(int index) { switch (index) { case 0: return HashAlgId; case 1: return MajorVersion; case 2: return MinorVersion; case 3: return BuildNumber; case 4: return RevisionNumber; case 5: return Flags; case 6: return PublicKey; case 7: return Name; case 8: return Locale; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: HashAlgId = value; break; case 1: MajorVersion = (ushort)value; break; case 2: MinorVersion = (ushort)value; break; case 3: BuildNumber = (ushort)value; break; case 4: RevisionNumber = (ushort)value; break; case 5: Flags = value; break; case 6: PublicKey = value; break; case 7: Name = value; break; case 8: Locale = value; break; default: break; } } } /// /// Raw contents of an uncompressed AssemblyProcessor table row /// public sealed class RawAssemblyProcessorRow : IRawRow { /// public uint Processor; /// Default constructor public RawAssemblyProcessorRow() { } /// Constructor public RawAssemblyProcessorRow(uint Processor) { this.Processor = Processor; } /// public uint Read(int index) { switch (index) { case 0: return Processor; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Processor = value; break; default: break; } } } /// /// Raw contents of an uncompressed AssemblyOS table row /// public sealed class RawAssemblyOSRow : IRawRow { /// public uint OSPlatformId; /// public uint OSMajorVersion; /// public uint OSMinorVersion; /// Default constructor public RawAssemblyOSRow() { } /// Constructor public RawAssemblyOSRow(uint OSPlatformId, uint OSMajorVersion, uint OSMinorVersion) { this.OSPlatformId = OSPlatformId; this.OSMajorVersion = OSMajorVersion; this.OSMinorVersion = OSMinorVersion; } /// public uint Read(int index) { switch (index) { case 0: return OSPlatformId; case 1: return OSMajorVersion; case 2: return OSMinorVersion; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: OSPlatformId = value; break; case 1: OSMajorVersion = value; break; case 2: OSMinorVersion = value; break; default: break; } } } /// /// Raw contents of an uncompressed AssemblyRef table row /// public sealed class RawAssemblyRefRow : IRawRow { /// public ushort MajorVersion; /// public ushort MinorVersion; /// public ushort BuildNumber; /// public ushort RevisionNumber; /// public uint Flags; /// public uint PublicKeyOrToken; /// public uint Name; /// public uint Locale; /// public uint HashValue; /// Default constructor public RawAssemblyRefRow() { } /// Constructor public RawAssemblyRefRow(ushort MajorVersion, ushort MinorVersion, ushort BuildNumber, ushort RevisionNumber, uint Flags, uint PublicKeyOrToken, uint Name, uint Locale, uint HashValue) { this.MajorVersion = MajorVersion; this.MinorVersion = MinorVersion; this.BuildNumber = BuildNumber; this.RevisionNumber = RevisionNumber; this.Flags = Flags; this.PublicKeyOrToken = PublicKeyOrToken; this.Name = Name; this.Locale = Locale; this.HashValue = HashValue; } /// public uint Read(int index) { switch (index) { case 0: return MajorVersion; case 1: return MinorVersion; case 2: return BuildNumber; case 3: return RevisionNumber; case 4: return Flags; case 5: return PublicKeyOrToken; case 6: return Name; case 7: return Locale; case 8: return HashValue; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: MajorVersion = (ushort)value; break; case 1: MinorVersion = (ushort)value; break; case 2: BuildNumber = (ushort)value; break; case 3: RevisionNumber = (ushort)value; break; case 4: Flags = value; break; case 5: PublicKeyOrToken = value; break; case 6: Name = value; break; case 7: Locale = value; break; case 8: HashValue = value; break; default: break; } } } /// /// Raw contents of an uncompressed AssemblyRefProcessor table row /// public sealed class RawAssemblyRefProcessorRow : IRawRow { /// public uint Processor; /// public uint AssemblyRef; /// Default constructor public RawAssemblyRefProcessorRow() { } /// Constructor public RawAssemblyRefProcessorRow(uint Processor, uint AssemblyRef) { this.Processor = Processor; this.AssemblyRef = AssemblyRef; } /// public uint Read(int index) { switch (index) { case 0: return Processor; case 1: return AssemblyRef; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Processor = value; break; case 1: AssemblyRef = value; break; default: break; } } } /// /// Raw contents of an uncompressed AssemblyRefOS table row /// public sealed class RawAssemblyRefOSRow : IRawRow { /// public uint OSPlatformId; /// public uint OSMajorVersion; /// public uint OSMinorVersion; /// public uint AssemblyRef; /// Default constructor public RawAssemblyRefOSRow() { } /// Constructor public RawAssemblyRefOSRow(uint OSPlatformId, uint OSMajorVersion, uint OSMinorVersion, uint AssemblyRef) { this.OSPlatformId = OSPlatformId; this.OSMajorVersion = OSMajorVersion; this.OSMinorVersion = OSMinorVersion; this.AssemblyRef = AssemblyRef; } /// public uint Read(int index) { switch (index) { case 0: return OSPlatformId; case 1: return OSMajorVersion; case 2: return OSMinorVersion; case 3: return AssemblyRef; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: OSPlatformId = value; break; case 1: OSMajorVersion = value; break; case 2: OSMinorVersion = value; break; case 3: AssemblyRef = value; break; default: break; } } } /// /// Raw contents of an uncompressed File table row /// public sealed class RawFileRow : IRawRow { /// public uint Flags; /// public uint Name; /// public uint HashValue; /// Default constructor public RawFileRow() { } /// Constructor public RawFileRow(uint Flags, uint Name, uint HashValue) { this.Flags = Flags; this.Name = Name; this.HashValue = HashValue; } /// public uint Read(int index) { switch (index) { case 0: return Flags; case 1: return Name; case 2: return HashValue; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Flags = value; break; case 1: Name = value; break; case 2: HashValue = value; break; default: break; } } } /// /// Raw contents of an uncompressed ExportedType table row /// public sealed class RawExportedTypeRow : IRawRow { /// public uint Flags; /// public uint TypeDefId; /// public uint TypeName; /// public uint TypeNamespace; /// public uint Implementation; /// Default constructor public RawExportedTypeRow() { } /// Constructor public RawExportedTypeRow(uint Flags, uint TypeDefId, uint TypeName, uint TypeNamespace, uint Implementation) { this.Flags = Flags; this.TypeDefId = TypeDefId; this.TypeName = TypeName; this.TypeNamespace = TypeNamespace; this.Implementation = Implementation; } /// public uint Read(int index) { switch (index) { case 0: return Flags; case 1: return TypeDefId; case 2: return TypeName; case 3: return TypeNamespace; case 4: return Implementation; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Flags = value; break; case 1: TypeDefId = value; break; case 2: TypeName = value; break; case 3: TypeNamespace = value; break; case 4: Implementation = value; break; default: break; } } } /// /// Raw contents of an uncompressed ManifestResource table row /// public sealed class RawManifestResourceRow : IRawRow { /// public uint Offset; /// public uint Flags; /// public uint Name; /// public uint Implementation; /// Default constructor public RawManifestResourceRow() { } /// Constructor public RawManifestResourceRow(uint Offset, uint Flags, uint Name, uint Implementation) { this.Offset = Offset; this.Flags = Flags; this.Name = Name; this.Implementation = Implementation; } /// public uint Read(int index) { switch (index) { case 0: return Offset; case 1: return Flags; case 2: return Name; case 3: return Implementation; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Offset = value; break; case 1: Flags = value; break; case 2: Name = value; break; case 3: Implementation = value; break; default: break; } } } /// /// Raw contents of an uncompressed NestedClass table row /// public sealed class RawNestedClassRow : IRawRow { /// public uint NestedClass; /// public uint EnclosingClass; /// Default constructor public RawNestedClassRow() { } /// Constructor public RawNestedClassRow(uint NestedClass, uint EnclosingClass) { this.NestedClass = NestedClass; this.EnclosingClass = EnclosingClass; } /// public uint Read(int index) { switch (index) { case 0: return NestedClass; case 1: return EnclosingClass; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: NestedClass = value; break; case 1: EnclosingClass = value; break; default: break; } } } /// /// Raw contents of an uncompressed GenericParam table row /// public sealed class RawGenericParamRow : IRawRow { /// public ushort Number; /// public ushort Flags; /// public uint Owner; /// public uint Name; /// public uint Kind; /// Default constructor public RawGenericParamRow() { } /// Constructor public RawGenericParamRow(ushort Number, ushort Flags, uint Owner, uint Name, uint Kind) { this.Number = Number; this.Flags = Flags; this.Owner = Owner; this.Name = Name; this.Kind = Kind; } /// Constructor public RawGenericParamRow(ushort Number, ushort Flags, uint Owner, uint Name) { this.Number = Number; this.Flags = Flags; this.Owner = Owner; this.Name = Name; } /// public uint Read(int index) { switch (index) { case 0: return Number; case 1: return Flags; case 2: return Owner; case 3: return Name; case 4: return Kind; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Number = (ushort)value; break; case 1: Flags = (ushort)value; break; case 2: Owner = value; break; case 3: Name = value; break; case 4: Kind = value; break; default: break; } } } /// /// Raw contents of an uncompressed MethodSpec table row /// public sealed class RawMethodSpecRow : IRawRow { /// public uint Method; /// public uint Instantiation; /// Default constructor public RawMethodSpecRow() { } /// Constructor public RawMethodSpecRow(uint Method, uint Instantiation) { this.Method = Method; this.Instantiation = Instantiation; } /// public uint Read(int index) { switch (index) { case 0: return Method; case 1: return Instantiation; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Method = value; break; case 1: Instantiation = value; break; default: break; } } } /// /// Raw contents of an uncompressed GenericParamConstraint table row /// public sealed class RawGenericParamConstraintRow : IRawRow { /// public uint Owner; /// public uint Constraint; /// Default constructor public RawGenericParamConstraintRow() { } /// Constructor public RawGenericParamConstraintRow(uint Owner, uint Constraint) { this.Owner = Owner; this.Constraint = Constraint; } /// public uint Read(int index) { switch (index) { case 0: return Owner; case 1: return Constraint; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Owner = value; break; case 1: Constraint = value; break; default: break; } } } /// /// Raw contents of an uncompressed Document table row /// public sealed class RawDocumentRow : IRawRow { /// public uint Name; /// public uint HashAlgorithm; /// public uint Hash; /// public uint Language; /// Default constructor public RawDocumentRow() { } /// Constructor public RawDocumentRow(uint Name, uint HashAlgorithm, uint Hash, uint Language) { this.Name = Name; this.HashAlgorithm = HashAlgorithm; this.Hash = Hash; this.Language = Language; } /// public uint Read(int index) { switch (index) { case 0: return Name; case 1: return HashAlgorithm; case 2: return Hash; case 3: return Language; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Name = value; break; case 1: HashAlgorithm = value; break; case 2: Hash = value; break; case 3: Language = value; break; default: break; } } } /// /// Raw contents of an uncompressed MethodDebugInformation table row /// public sealed class RawMethodDebugInformationRow : IRawRow { /// public uint Document; /// public uint SequencePoints; /// Default constructor public RawMethodDebugInformationRow() { } /// Constructor public RawMethodDebugInformationRow(uint Document, uint SequencePoints) { this.Document = Document; this.SequencePoints = SequencePoints; } /// public uint Read(int index) { switch (index) { case 0: return Document; case 1: return SequencePoints; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Document = value; break; case 1: SequencePoints = value; break; default: break; } } } /// /// Raw contents of an uncompressed LocalScope table row /// public sealed class RawLocalScopeRow : IRawRow { /// public uint Method; /// public uint ImportScope; /// public uint VariableList; /// public uint ConstantList; /// public uint StartOffset; /// public uint Length; /// Default constructor public RawLocalScopeRow() { } /// Constructor public RawLocalScopeRow(uint Method, uint ImportScope, uint VariableList, uint ConstantList, uint StartOffset, uint Length) { this.Method = Method; this.ImportScope = ImportScope; this.VariableList = VariableList; this.ConstantList = ConstantList; this.StartOffset = StartOffset; this.Length = Length; } /// public uint Read(int index) { switch (index) { case 0: return Method; case 1: return ImportScope; case 2: return VariableList; case 3: return ConstantList; case 4: return StartOffset; case 5: return Length; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Method = value; break; case 1: ImportScope = value; break; case 2: VariableList = value; break; case 3: ConstantList = value; break; case 4: StartOffset = value; break; case 5: Length = value; break; default: break; } } } /// /// Raw contents of an uncompressed LocalVariable table row /// public sealed class RawLocalVariableRow : IRawRow { /// public ushort Attributes; /// public ushort Index; /// public uint Name; /// Default constructor public RawLocalVariableRow() { } /// Constructor public RawLocalVariableRow(ushort Attributes, ushort Index, uint Name) { this.Attributes = Attributes; this.Index = Index; this.Name = Name; } /// public uint Read(int index) { switch (index) { case 0: return Attributes; case 1: return Index; case 2: return Name; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Attributes = (ushort)value; break; case 1: Index = (ushort)value; break; case 2: Name = value; break; default: break; } } } /// /// Raw contents of an uncompressed LocalConstant table row /// public sealed class RawLocalConstantRow : IRawRow { /// public uint Name; /// public uint Signature; /// Default constructor public RawLocalConstantRow() { } /// Constructor public RawLocalConstantRow(uint Name, uint Signature) { this.Name = Name; this.Signature = Signature; } /// public uint Read(int index) { switch (index) { case 0: return Name; case 1: return Signature; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Name = value; break; case 1: Signature = value; break; default: break; } } } /// /// Raw contents of an uncompressed ImportScope table row /// public sealed class RawImportScopeRow : IRawRow { /// public uint Parent; /// public uint Imports; /// Default constructor public RawImportScopeRow() { } /// Constructor public RawImportScopeRow(uint Parent, uint Imports) { this.Parent = Parent; this.Imports = Imports; } /// public uint Read(int index) { switch (index) { case 0: return Parent; case 1: return Imports; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Parent = value; break; case 1: Imports = value; break; default: break; } } } /// /// Raw contents of an uncompressed StateMachineMethod table row /// public sealed class RawStateMachineMethodRow : IRawRow { /// public uint MoveNextMethod; /// public uint KickoffMethod; /// Default constructor public RawStateMachineMethodRow() { } /// Constructor public RawStateMachineMethodRow(uint MoveNextMethod, uint KickoffMethod) { this.MoveNextMethod = MoveNextMethod; this.KickoffMethod = KickoffMethod; } /// public uint Read(int index) { switch (index) { case 0: return MoveNextMethod; case 1: return KickoffMethod; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: MoveNextMethod = value; break; case 1: KickoffMethod = value; break; default: break; } } } /// /// Raw contents of an uncompressed CustomDebugInformation table row /// public sealed class RawCustomDebugInformationRow : IRawRow { /// public uint Parent; /// public uint Kind; /// public uint Value; /// Default constructor public RawCustomDebugInformationRow() { } /// Constructor public RawCustomDebugInformationRow(uint Parent, uint Kind, uint Value) { this.Parent = Parent; this.Kind = Kind; this.Value = Value; } /// public uint Read(int index) { switch (index) { case 0: return Parent; case 1: return Kind; case 2: return Value; default: return 0; } } /// public void Write(int index, uint value) { switch (index) { case 0: Parent = value; break; case 1: Kind = value; break; case 2: Value = value; break; default: break; } } } } dnlib-2.1_VS2010/src/DotNet/MD/RidList.cs000066400000000000000000000066531325033663500175640ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Diagnostics; namespace dnlib.DotNet.MD { /// /// Stores a list of rids /// [DebuggerDisplay("Length = {Length}")] public abstract class RidList { /// /// The empty /// public static readonly RidList Empty = new ContiguousRidList(0, 0); /// /// Gets the number of rids it will iterate over (UInt32) /// public abstract uint Length { get; } /// /// Gets the number of rids it will iterate over (Int32) /// public abstract int Count { get; } /// /// Gets the 'th rid /// /// Index. Must be < /// A rid or 0 if is invalid public abstract uint this[uint index] { get; } /// /// Gets the 'th rid /// /// Index. Must be < /// A rid or 0 if is invalid public abstract uint this[int index] { get; } } /// /// A where the rids are contiguous /// sealed class ContiguousRidList : RidList { readonly uint startRid; readonly uint length; /// /// Gets the start rid /// public uint StartRID { get { return startRid; } } /// public override uint Length { get { return length; } } /// public override int Count { get { return (int)length; } } /// public override uint this[uint index] { get { if (index >= length) return 0; return startRid + index; } } /// public override uint this[int index] { get { return this[(uint)index]; } } /// /// Constructor /// /// First rid to return /// Number of rids to return public ContiguousRidList(uint startRid, uint length) { this.startRid = startRid; this.length = length; } } /// /// A where the returned rids aren't necessarily contiguous. /// This should be used if eg. the pointer tables are present. /// sealed class RandomRidList : RidList { readonly IList indexToRid; /// public override uint Length { get { return (uint)indexToRid.Count; } } /// public override int Count { get { return indexToRid.Count; } } /// public override uint this[uint index] { get { if (index >= (uint)indexToRid.Count) return 0; return indexToRid[(int)index]; } } /// public override uint this[int index] { get { return this[(uint)index]; } } /// /// Default constructor /// public RandomRidList() { this.indexToRid = new List(); } /// /// Constructor /// /// Approximate number of rids that will be returned public RandomRidList(int capacity) { this.indexToRid = new List(capacity); } /// /// Add a new rid that should be returned /// /// The rid public void Add(uint rid) { indexToRid.Add(rid); } } } dnlib-2.1_VS2010/src/DotNet/MD/StorageFlags.cs000066400000000000000000000007441325033663500205660ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet.MD { /// /// Storage flags found in the MD header /// [Flags] public enum StorageFlags : byte { /// /// Normal flags /// Normal = 0, /// /// More data after the header but before the streams. /// /// The CLR will fail to load the file if this flag (or any other bits) is set. ExtraData = 1, } } dnlib-2.1_VS2010/src/DotNet/MD/StreamHeader.cs000066400000000000000000000035541325033663500205530ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.Text; using dnlib.IO; namespace dnlib.DotNet.MD { /// /// A metadata stream header /// [DebuggerDisplay("O:{offset} L:{streamSize} {name}")] public sealed class StreamHeader : FileSection { readonly uint offset; readonly uint streamSize; readonly string name; /// /// The offset of the stream relative to the start of the MetaData header /// public uint Offset { get { return offset; } } /// /// The size of the stream /// public uint StreamSize { get { return streamSize; } } /// /// The name of the stream /// public string Name { get { return name; } } /// /// Constructor /// /// PE file reader pointing to the start of this section /// Verify section /// Thrown if verification fails public StreamHeader(IImageStream reader, bool verify) { SetStartOffset(reader); this.offset = reader.ReadUInt32(); this.streamSize = reader.ReadUInt32(); this.name = ReadString(reader, 32, verify); SetEndoffset(reader); if (verify && offset + size < offset) throw new BadImageFormatException("Invalid stream header"); } static string ReadString(IImageStream reader, int maxLen, bool verify) { var origPos = reader.Position; var sb = new StringBuilder(maxLen); int i; for (i = 0; i < maxLen; i++) { byte b = reader.ReadByte(); if (b == 0) break; sb.Append((char)b); } if (verify && i == maxLen) throw new BadImageFormatException("Invalid stream name string"); if (i != maxLen) reader.Position = origPos + ((i + 1 + 3) & ~3); return sb.ToString(); } } } dnlib-2.1_VS2010/src/DotNet/MD/StringsStream.cs000066400000000000000000000025261325033663500210120ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.IO; namespace dnlib.DotNet.MD { /// /// Represents the #Strings stream /// public sealed class StringsStream : HeapStream { /// public StringsStream() { } /// public StringsStream(IImageStream imageStream, StreamHeader streamHeader) : base(imageStream, streamHeader) { } /// /// Reads a /// /// Offset of string /// A instance or null if invalid offset public UTF8String Read(uint offset) { if (offset >= ImageStreamLength) return null; byte[] data; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(offset); data = reader.ReadBytesUntilByte(0); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif if (data == null) return null; return new UTF8String(data); } /// /// Reads a . The empty string is returned if /// is invalid. /// /// Offset of string /// A instance public UTF8String ReadNoNull(uint offset) { return Read(offset) ?? UTF8String.Empty; } } } dnlib-2.1_VS2010/src/DotNet/MD/Table.cs000066400000000000000000000071031325033663500172300ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.MD { /// /// The metadata tables /// public enum Table : byte { /// Module table (00h) Module, /// TypeRef table (01h) TypeRef, /// TypeDef table (02h) TypeDef, /// FieldPtr table (03h) FieldPtr, /// Field table (04h) Field, /// MethodPtr table (05h) MethodPtr, /// Method table (06h) Method, /// ParamPtr table (07h) ParamPtr, /// Param table (08h) Param, /// InterfaceImpl table (09h) InterfaceImpl, /// MemberRef table (0Ah) MemberRef, /// Constant table (0Bh) Constant, /// CustomAttribute table (0Ch) CustomAttribute, /// FieldMarshal table (0Dh) FieldMarshal, /// DeclSecurity table (0Eh) DeclSecurity, /// ClassLayout table (0Fh) ClassLayout, /// FieldLayout table (10h) FieldLayout, /// StandAloneSig table (11h) StandAloneSig, /// EventMap table (12h) EventMap, /// EventPtr table (13h) EventPtr, /// Event table (14h) Event, /// PropertyMap table (15h) PropertyMap, /// PropertyPtr table (16h) PropertyPtr, /// Property table (17h) Property, /// MethodSemantics table (18h) MethodSemantics, /// MethodImpl table (19h) MethodImpl, /// ModuleRef table (1Ah) ModuleRef, /// TypeSpec table (1Bh) TypeSpec, /// ImplMap table (1Ch) ImplMap, /// FieldRVA table (1Dh) FieldRVA, /// ENCLog table (1Eh) ENCLog, /// ENCMap table (1Fh) ENCMap, /// Assembly table (20h) Assembly, /// AssemblyProcessor table (21h) AssemblyProcessor, /// AssemblyOS table (22h) AssemblyOS, /// AssemblyRef table (23h) AssemblyRef, /// AssemblyRefProcessor table (24h) AssemblyRefProcessor, /// AssemblyRefOS table (25h) AssemblyRefOS, /// File table (26h) File, /// ExportedType table (27h) ExportedType, /// ManifestResource table (28h) ManifestResource, /// NestedClass table (29h) NestedClass, /// GenericParam table (2Ah) GenericParam, /// MethodSpec table (2Bh) MethodSpec, /// GenericParamConstraint table (2Ch) GenericParamConstraint, /// (Portable PDB) Document table (30h) Document = 0x30, /// (Portable PDB) MethodDebugInformation table (31h) MethodDebugInformation, /// (Portable PDB) LocalScope table (32h) LocalScope, /// (Portable PDB) LocalVariable table (33h) LocalVariable, /// (Portable PDB) LocalConstant table (34h) LocalConstant, /// (Portable PDB) ImportScope table (35h) ImportScope, /// (Portable PDB) StateMachineMethod table (36h) StateMachineMethod, /// (Portable PDB) CustomDebugInformation table (37h) CustomDebugInformation, } } dnlib-2.1_VS2010/src/DotNet/MD/TableInfo.cs000066400000000000000000000032101325033663500200370ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Diagnostics; namespace dnlib.DotNet.MD { /// /// Info about one MD table /// [DebuggerDisplay("{rowSize} {name}")] public sealed class TableInfo { readonly Table table; int rowSize; readonly IList columns; readonly string name; /// /// Returns the table type /// public Table Table { get { return table; } } /// /// Returns the total size of a row in bytes /// public int RowSize { get { return rowSize; } internal set { rowSize = value; } } /// /// Returns all the columns /// public IList Columns { get { return columns; } } /// /// Returns the name of the table /// public string Name { get { return name; } } /// /// Constructor /// /// Table type /// Table name /// All columns public TableInfo(Table table, string name, IList columns) { this.table = table; this.name = name; this.columns = columns; } /// /// Constructor /// /// Table type /// Table name /// All columns /// Row size public TableInfo(Table table, string name, IList columns, int rowSize) { this.table = table; this.name = name; this.columns = columns; this.rowSize = rowSize; } } } dnlib-2.1_VS2010/src/DotNet/MD/TablesStream.cs000066400000000000000000000312251325033663500205710ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; using dnlib.Threading; namespace dnlib.DotNet.MD { /// /// .NET metadata tables stream /// public sealed partial class TablesStream : DotNetStream { bool initialized; uint reserved1; byte majorVersion; byte minorVersion; MDStreamFlags flags; byte log2Rid; ulong validMask; ulong sortedMask; uint extraData; MDTable[] mdTables; HotTableStream hotTableStream; IColumnReader columnReader; IRowReader methodRowReader; #pragma warning disable 1591 // XML doc comment public MDTable ModuleTable { get; private set; } public MDTable TypeRefTable { get; private set; } public MDTable TypeDefTable { get; private set; } public MDTable FieldPtrTable { get; private set; } public MDTable FieldTable { get; private set; } public MDTable MethodPtrTable { get; private set; } public MDTable MethodTable { get; private set; } public MDTable ParamPtrTable { get; private set; } public MDTable ParamTable { get; private set; } public MDTable InterfaceImplTable { get; private set; } public MDTable MemberRefTable { get; private set; } public MDTable ConstantTable { get; private set; } public MDTable CustomAttributeTable { get; private set; } public MDTable FieldMarshalTable { get; private set; } public MDTable DeclSecurityTable { get; private set; } public MDTable ClassLayoutTable { get; private set; } public MDTable FieldLayoutTable { get; private set; } public MDTable StandAloneSigTable { get; private set; } public MDTable EventMapTable { get; private set; } public MDTable EventPtrTable { get; private set; } public MDTable EventTable { get; private set; } public MDTable PropertyMapTable { get; private set; } public MDTable PropertyPtrTable { get; private set; } public MDTable PropertyTable { get; private set; } public MDTable MethodSemanticsTable { get; private set; } public MDTable MethodImplTable { get; private set; } public MDTable ModuleRefTable { get; private set; } public MDTable TypeSpecTable { get; private set; } public MDTable ImplMapTable { get; private set; } public MDTable FieldRVATable { get; private set; } public MDTable ENCLogTable { get; private set; } public MDTable ENCMapTable { get; private set; } public MDTable AssemblyTable { get; private set; } public MDTable AssemblyProcessorTable { get; private set; } public MDTable AssemblyOSTable { get; private set; } public MDTable AssemblyRefTable { get; private set; } public MDTable AssemblyRefProcessorTable { get; private set; } public MDTable AssemblyRefOSTable { get; private set; } public MDTable FileTable { get; private set; } public MDTable ExportedTypeTable { get; private set; } public MDTable ManifestResourceTable { get; private set; } public MDTable NestedClassTable { get; private set; } public MDTable GenericParamTable { get; private set; } public MDTable MethodSpecTable { get; private set; } public MDTable GenericParamConstraintTable { get; private set; } public MDTable DocumentTable { get; private set; } public MDTable MethodDebugInformationTable { get; private set; } public MDTable LocalScopeTable { get; private set; } public MDTable LocalVariableTable { get; private set; } public MDTable LocalConstantTable { get; private set; } public MDTable ImportScopeTable { get; private set; } public MDTable StateMachineMethodTable { get; private set; } public MDTable CustomDebugInformationTable { get; private set; } #pragma warning restore #if THREAD_SAFE internal readonly Lock theLock = Lock.Create(); #endif internal HotTableStream HotTableStream { set { hotTableStream = value; } } /// /// Gets/sets the column reader /// public IColumnReader ColumnReader { get { return columnReader; } set { columnReader = value; } } /// /// Gets/sets the Method table reader /// public IRowReader MethodRowReader { get { return methodRowReader; } set { methodRowReader = value; } } /// /// Gets the reserved field /// public uint Reserved1 { get { return reserved1; } } /// /// Gets the version. The major version is in the upper 8 bits, and the minor version /// is in the lower 8 bits. /// public ushort Version { get { return (ushort)((majorVersion << 8) | minorVersion); } } /// /// Gets /// public MDStreamFlags Flags { get { return flags; } } /// /// Gets the reserved log2 rid field /// public byte Log2Rid { get { return log2Rid; } } /// /// Gets the valid mask /// public ulong ValidMask { get { return validMask; } } /// /// Gets the sorted mask /// public ulong SortedMask { get { return sortedMask; } } /// /// Gets the extra data /// public uint ExtraData { get { return extraData; } } /// /// Gets the MD tables /// public MDTable[] MDTables { get { return mdTables; } } /// /// Gets the bit /// public bool HasBigStrings { get { return (flags & MDStreamFlags.BigStrings) != 0; } } /// /// Gets the bit /// public bool HasBigGUID { get { return (flags & MDStreamFlags.BigGUID) != 0; } } /// /// Gets the bit /// public bool HasBigBlob { get { return (flags & MDStreamFlags.BigBlob) != 0; } } /// /// Gets the bit /// public bool HasPadding { get { return (flags & MDStreamFlags.Padding) != 0; } } /// /// Gets the bit /// public bool HasDeltaOnly { get { return (flags & MDStreamFlags.DeltaOnly) != 0; } } /// /// Gets the bit /// public bool HasExtraData { get { return (flags & MDStreamFlags.ExtraData) != 0; } } /// /// Gets the bit /// public bool HasDelete { get { return (flags & MDStreamFlags.HasDelete) != 0; } } /// public TablesStream(IImageStream imageStream, StreamHeader streamHeader) : base(imageStream, streamHeader) { } /// /// Initializes MD tables /// /// Type system table rows (from #Pdb stream) public void Initialize(uint[] typeSystemTableRows) { if (initialized) throw new Exception("Initialize() has already been called"); initialized = true; reserved1 = imageStream.ReadUInt32(); majorVersion = imageStream.ReadByte(); minorVersion = imageStream.ReadByte(); flags = (MDStreamFlags)imageStream.ReadByte(); log2Rid = imageStream.ReadByte(); validMask = imageStream.ReadUInt64(); sortedMask = imageStream.ReadUInt64(); int maxPresentTables; var dnTableSizes = new DotNetTableSizes(); var tableInfos = dnTableSizes.CreateTables(majorVersion, minorVersion, out maxPresentTables); if (typeSystemTableRows != null) maxPresentTables = DotNetTableSizes.normalMaxTables; mdTables = new MDTable[tableInfos.Length]; ulong valid = validMask; var sizes = new uint[64]; for (int i = 0; i < 64; valid >>= 1, i++) { uint rows = (valid & 1) == 0 ? 0 : imageStream.ReadUInt32(); if (i >= maxPresentTables) rows = 0; sizes[i] = rows; if (i < mdTables.Length) mdTables[i] = new MDTable((Table)i, rows, tableInfos[i]); } if (HasExtraData) extraData = imageStream.ReadUInt32(); var debugSizes = sizes; if (typeSystemTableRows != null) { debugSizes = new uint[sizes.Length]; for (int i = 0; i < 64; i++) { if (DotNetTableSizes.IsSystemTable((Table)i)) debugSizes[i] = typeSystemTableRows[i]; else debugSizes[i] = sizes[i]; } } dnTableSizes.InitializeSizes(HasBigStrings, HasBigGUID, HasBigBlob, sizes, debugSizes); var currentPos = (FileOffset)imageStream.Position; foreach (var mdTable in mdTables) { var dataLen = (long)mdTable.TableInfo.RowSize * (long)mdTable.Rows; mdTable.ImageStream = imageStream.Create(currentPos, dataLen); var newPos = currentPos + (uint)dataLen; if (newPos < currentPos) throw new BadImageFormatException("Too big MD table"); currentPos = newPos; } InitializeTables(); } void InitializeTables() { ModuleTable = mdTables[(int)Table.Module]; TypeRefTable = mdTables[(int)Table.TypeRef]; TypeDefTable = mdTables[(int)Table.TypeDef]; FieldPtrTable = mdTables[(int)Table.FieldPtr]; FieldTable = mdTables[(int)Table.Field]; MethodPtrTable = mdTables[(int)Table.MethodPtr]; MethodTable = mdTables[(int)Table.Method]; ParamPtrTable = mdTables[(int)Table.ParamPtr]; ParamTable = mdTables[(int)Table.Param]; InterfaceImplTable = mdTables[(int)Table.InterfaceImpl]; MemberRefTable = mdTables[(int)Table.MemberRef]; ConstantTable = mdTables[(int)Table.Constant]; CustomAttributeTable = mdTables[(int)Table.CustomAttribute]; FieldMarshalTable = mdTables[(int)Table.FieldMarshal]; DeclSecurityTable = mdTables[(int)Table.DeclSecurity]; ClassLayoutTable = mdTables[(int)Table.ClassLayout]; FieldLayoutTable = mdTables[(int)Table.FieldLayout]; StandAloneSigTable = mdTables[(int)Table.StandAloneSig]; EventMapTable = mdTables[(int)Table.EventMap]; EventPtrTable = mdTables[(int)Table.EventPtr]; EventTable = mdTables[(int)Table.Event]; PropertyMapTable = mdTables[(int)Table.PropertyMap]; PropertyPtrTable = mdTables[(int)Table.PropertyPtr]; PropertyTable = mdTables[(int)Table.Property]; MethodSemanticsTable = mdTables[(int)Table.MethodSemantics]; MethodImplTable = mdTables[(int)Table.MethodImpl]; ModuleRefTable = mdTables[(int)Table.ModuleRef]; TypeSpecTable = mdTables[(int)Table.TypeSpec]; ImplMapTable = mdTables[(int)Table.ImplMap]; FieldRVATable = mdTables[(int)Table.FieldRVA]; ENCLogTable = mdTables[(int)Table.ENCLog]; ENCMapTable = mdTables[(int)Table.ENCMap]; AssemblyTable = mdTables[(int)Table.Assembly]; AssemblyProcessorTable = mdTables[(int)Table.AssemblyProcessor]; AssemblyOSTable = mdTables[(int)Table.AssemblyOS]; AssemblyRefTable = mdTables[(int)Table.AssemblyRef]; AssemblyRefProcessorTable = mdTables[(int)Table.AssemblyRefProcessor]; AssemblyRefOSTable = mdTables[(int)Table.AssemblyRefOS]; FileTable = mdTables[(int)Table.File]; ExportedTypeTable = mdTables[(int)Table.ExportedType]; ManifestResourceTable = mdTables[(int)Table.ManifestResource]; NestedClassTable = mdTables[(int)Table.NestedClass]; GenericParamTable = mdTables[(int)Table.GenericParam]; MethodSpecTable = mdTables[(int)Table.MethodSpec]; GenericParamConstraintTable = mdTables[(int)Table.GenericParamConstraint]; DocumentTable = mdTables[(int)Table.Document]; MethodDebugInformationTable = mdTables[(int)Table.MethodDebugInformation]; LocalScopeTable = mdTables[(int)Table.LocalScope]; LocalVariableTable = mdTables[(int)Table.LocalVariable]; LocalConstantTable = mdTables[(int)Table.LocalConstant]; ImportScopeTable = mdTables[(int)Table.ImportScope]; StateMachineMethodTable = mdTables[(int)Table.StateMachineMethod]; CustomDebugInformationTable = mdTables[(int)Table.CustomDebugInformation]; } /// protected override void Dispose(bool disposing) { if (disposing) { var mt = mdTables; if (mt != null) { foreach (var mdTable in mt) { if (mdTable != null) mdTable.Dispose(); } mdTables = null; } } base.Dispose(disposing); } /// /// Returns a MD table /// /// The table type /// A or null if table doesn't exist public MDTable Get(Table table) { int index = (int)table; if ((uint)index >= (uint)mdTables.Length) return null; return mdTables[index]; } /// /// Checks whether a table exists /// /// The table type /// true if the table exists public bool HasTable(Table table) { return (uint)table < (uint)mdTables.Length; } /// /// Checks whether table is sorted /// /// The table public bool IsSorted(MDTable table) { int index = (int)table.Table; if ((uint)index >= 64) return false; return (sortedMask & (1UL << index)) != 0; } } } dnlib-2.1_VS2010/src/DotNet/MD/TablesStream_Read.cs000066400000000000000000001726671325033663500215440ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.MD { public partial class TablesStream { IBinaryReader GetReader_NoLock(MDTable table, uint rid) { IBinaryReader reader; if (hotTableStream != null) { reader = hotTableStream.GetTableReader(table, rid); if (reader != null) return reader; } reader = table.ImageStream; reader.Position = (rid - 1) * table.TableInfo.RowSize; return reader; } /// /// Reads a raw Module row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawModuleRow ReadModuleRow(uint rid) { var table = ModuleTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawModuleRow(reader.ReadUInt16(), columns[1].Read(reader), columns[2].Read(reader), columns[3].Read(reader), columns[4].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Module row /// /// Row ID /// /// /// /// /// internal uint ReadModuleRow(uint rid, out ushort generation, out uint name, out uint mvid, out uint encId) { var table = ModuleTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; generation = reader.ReadUInt16(); name = columns[1].Read(reader); mvid = columns[2].Read(reader); encId = columns[3].Read(reader); return columns[4].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw TypeRef row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawTypeRefRow ReadTypeRefRow(uint rid) { var table = TypeRefTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawTypeRefRow(columns[0].Read(reader), columns[1].Read(reader), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw TypeRef row /// /// Row ID /// /// /// internal uint ReadTypeRefRow(uint rid, out uint resolutionScope, out uint name) { var table = TypeRefTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; resolutionScope = columns[0].Read(reader); name = columns[1].Read(reader); return columns[2].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw TypeDef row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawTypeDefRow ReadTypeDefRow(uint rid) { var table = TypeDefTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawTypeDefRow(reader.ReadUInt32(), columns[1].Read(reader), columns[2].Read(reader), columns[3].Read(reader), columns[4].Read(reader), columns[5].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw TypeDef row. Doesn't read field/method rid list. /// /// Row ID /// /// /// /// internal uint ReadTypeDefRow(uint rid, out int flags, out uint name, out uint @namespace) { var table = TypeDefTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; flags = reader.ReadInt32(); name = columns[1].Read(reader); @namespace = columns[2].Read(reader); return columns[3].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw FieldPtr row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawFieldPtrRow ReadFieldPtrRow(uint rid) { var table = FieldPtrTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawFieldPtrRow(columns[0].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Field row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawFieldRow ReadFieldRow(uint rid) { var table = FieldTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawFieldRow(reader.ReadUInt16(), columns[1].Read(reader), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Field row /// /// Row ID /// /// /// internal uint ReadFieldRow(uint rid, out int flags, out uint name) { var table = FieldTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; flags = reader.ReadUInt16(); name = columns[1].Read(reader); return columns[2].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw MethodPtr row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawMethodPtrRow ReadMethodPtrRow(uint rid) { var table = MethodPtrTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawMethodPtrRow(columns[0].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Method row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawMethodRow ReadMethodRow(uint rid) { var table = MethodTable; if (table.IsInvalidRID(rid)) return null; var mrr = methodRowReader; if (mrr != null) { var row = mrr.ReadRow(rid); if (row != null) return row; } #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawMethodRow(reader.ReadUInt32(), reader.ReadUInt16(), reader.ReadUInt16(), columns[3].Read(reader), columns[4].Read(reader), columns[5].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Method row but not ParamList /// /// Row ID /// /// /// /// /// internal uint ReadMethodRow(uint rid, out RVA rva, out int implFlags, out int flags, out uint name) { var table = MethodTable; var mrr = methodRowReader; if (mrr != null) { var row = mrr.ReadRow(rid); if (row != null) { rva = (RVA)row.RVA; implFlags = row.ImplFlags; flags = row.Flags; name = row.Name; return row.Signature; } } #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; rva = (RVA)reader.ReadUInt32(); implFlags = reader.ReadUInt16(); flags = reader.ReadUInt16(); name = columns[3].Read(reader); return columns[4].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ParamPtr row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawParamPtrRow ReadParamPtrRow(uint rid) { var table = ParamPtrTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawParamPtrRow(columns[0].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Param row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawParamRow ReadParamRow(uint rid) { var table = ParamTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawParamRow(reader.ReadUInt16(), reader.ReadUInt16(), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Param row /// /// Row ID /// /// /// internal uint ReadParamRow(uint rid, out int flags, out ushort sequence) { var table = ParamTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; flags = reader.ReadUInt16(); sequence = reader.ReadUInt16(); return columns[2].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw InterfaceImpl row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawInterfaceImplRow ReadInterfaceImplRow(uint rid) { var table = InterfaceImplTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawInterfaceImplRow(columns[0].Read(reader), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw InterfaceImpl row /// /// Row ID /// The Interface field internal uint ReadInterfaceImplRow2(uint rid) { var table = InterfaceImplTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; reader.Position += columns[0].Size; return columns[1].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw MemberRef row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawMemberRefRow ReadMemberRefRow(uint rid) { var table = MemberRefTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawMemberRefRow(columns[0].Read(reader), columns[1].Read(reader), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw MemberRef row /// /// Row ID /// /// /// internal uint ReadMemberRefRow(uint rid, out uint @class, out uint name) { var table = MemberRefTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; @class = columns[0].Read(reader); name = columns[1].Read(reader); return columns[2].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Constant row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawConstantRow ReadConstantRow(uint rid) { var table = ConstantTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawConstantRow(reader.ReadByte(), reader.ReadByte(), columns[2].Read(reader), columns[3].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Constant row /// /// Row ID /// /// internal uint ReadConstantRow(uint rid, out ElementType type) { var table = ConstantTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; type = (ElementType)reader.ReadByte(); reader.Position += 1 + columns[2].Size; return columns[3].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw CustomAttribute row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawCustomAttributeRow ReadCustomAttributeRow(uint rid) { var table = CustomAttributeTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawCustomAttributeRow(columns[0].Read(reader), columns[1].Read(reader), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw FieldMarshal row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawFieldMarshalRow ReadFieldMarshalRow(uint rid) { var table = FieldMarshalTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawFieldMarshalRow(columns[0].Read(reader), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw DeclSecurity row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawDeclSecurityRow ReadDeclSecurityRow(uint rid) { var table = DeclSecurityTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawDeclSecurityRow(reader.ReadInt16(), columns[1].Read(reader), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw DeclSecurity row /// /// Row ID /// /// internal uint ReadDeclSecurityRow(uint rid, out SecurityAction action) { var table = DeclSecurityTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; action = (SecurityAction)reader.ReadInt16(); reader.Position += columns[1].Size; return columns[2].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ClassLayout row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawClassLayoutRow ReadClassLayoutRow(uint rid) { var table = ClassLayoutTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawClassLayoutRow(reader.ReadUInt16(), reader.ReadUInt32(), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ClassLayout row /// /// Row ID /// /// internal uint ReadClassLayoutRow(uint rid, out ushort packingSize) { var table = ClassLayoutTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; packingSize = reader.ReadUInt16(); return reader.ReadUInt32(); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw FieldLayout row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawFieldLayoutRow ReadFieldLayoutRow(uint rid) { var table = FieldLayoutTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawFieldLayoutRow(reader.ReadUInt32(), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw FieldLayout row /// /// Row ID /// internal uint? ReadFieldLayoutRow2(uint rid) { var table = FieldLayoutTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return reader.ReadUInt32(); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw StandAloneSig row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawStandAloneSigRow ReadStandAloneSigRow(uint rid) { var table = StandAloneSigTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawStandAloneSigRow(columns[0].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw StandAloneSig row /// /// Row ID /// internal uint ReadStandAloneSigRow2(uint rid) { var table = StandAloneSigTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return columns[0].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw EventMap row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawEventMapRow ReadEventMapRow(uint rid) { var table = EventMapTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawEventMapRow(columns[0].Read(reader), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw EventPtr row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawEventPtrRow ReadEventPtrRow(uint rid) { var table = EventPtrTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawEventPtrRow(columns[0].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Event row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawEventRow ReadEventRow(uint rid) { var table = EventTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawEventRow(reader.ReadUInt16(), columns[1].Read(reader), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Event row /// /// Row ID /// /// /// internal uint ReadEventRow(uint rid, out int eventFlags, out uint name) { var table = EventTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; eventFlags = reader.ReadUInt16(); name = columns[1].Read(reader); return columns[2].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw PropertyMap row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawPropertyMapRow ReadPropertyMapRow(uint rid) { var table = PropertyMapTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawPropertyMapRow(columns[0].Read(reader), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw PropertyPtr row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawPropertyPtrRow ReadPropertyPtrRow(uint rid) { var table = PropertyPtrTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawPropertyPtrRow(columns[0].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Property row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawPropertyRow ReadPropertyRow(uint rid) { var table = PropertyTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawPropertyRow(reader.ReadUInt16(), columns[1].Read(reader), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Property row /// /// Row ID /// /// /// internal uint ReadPropertyRow(uint rid, out int propFlags, out uint name) { var table = PropertyTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; propFlags = reader.ReadUInt16(); name = columns[1].Read(reader); return columns[2].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw MethodSemantics row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawMethodSemanticsRow ReadMethodSemanticsRow(uint rid) { var table = MethodSemanticsTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawMethodSemanticsRow(reader.ReadUInt16(), columns[1].Read(reader), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw MethodSemantics row /// /// Row ID /// /// internal uint ReadMethodSemanticsRow(uint rid, out MethodSemanticsAttributes semantic) { var table = MethodSemanticsTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; semantic = (MethodSemanticsAttributes)reader.ReadUInt16(); return columns[1].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw MethodImpl row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawMethodImplRow ReadMethodImplRow(uint rid) { var table = MethodImplTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawMethodImplRow(columns[0].Read(reader), columns[1].Read(reader), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw MethodImpl row /// /// Row ID /// /// internal uint ReadMethodImplRow(uint rid, out uint methodBody) { var table = MethodImplTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; reader.Position += columns[0].Size; methodBody = columns[1].Read(reader); return columns[2].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ModuleRef row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawModuleRefRow ReadModuleRefRow(uint rid) { var table = ModuleRefTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawModuleRefRow(columns[0].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ModuleRef row /// /// Row ID /// internal uint ReadModuleRefRow2(uint rid) { var table = ModuleRefTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return columns[0].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw TypeSpec row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawTypeSpecRow ReadTypeSpecRow(uint rid) { var table = TypeSpecTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawTypeSpecRow(columns[0].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw TypeSpec row /// /// Row ID /// internal uint ReadTypeSpecRow2(uint rid) { var table = TypeSpecTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return columns[0].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ImplMap row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawImplMapRow ReadImplMapRow(uint rid) { var table = ImplMapTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawImplMapRow(reader.ReadUInt16(), columns[1].Read(reader), columns[2].Read(reader), columns[3].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ImplMap row /// /// Row ID /// /// /// internal uint ReadImplMapRow(uint rid, out int attributes, out uint name) { var table = ImplMapTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; attributes = reader.ReadUInt16(); reader.Position += columns[1].Size; name = columns[2].Read(reader); return columns[3].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw FieldRVA row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawFieldRVARow ReadFieldRVARow(uint rid) { var table = FieldRVATable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawFieldRVARow(reader.ReadUInt32(), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw FieldRVA row /// /// Row ID /// /// internal bool ReadFieldRVARow(uint rid, out RVA rva) { var table = FieldRVATable; if (table.IsInvalidRID(rid)) { rva = 0; return false; } #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; rva = (RVA)reader.ReadUInt32(); return true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ENCLog row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawENCLogRow ReadENCLogRow(uint rid) { var table = ENCLogTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); return new RawENCLogRow(reader.ReadUInt32(), reader.ReadUInt32()); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ENCMap row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawENCMapRow ReadENCMapRow(uint rid) { var table = ENCMapTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); return new RawENCMapRow(reader.ReadUInt32()); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Assembly row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawAssemblyRow ReadAssemblyRow(uint rid) { var table = AssemblyTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawAssemblyRow(reader.ReadUInt32(), reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt32(), columns[6].Read(reader), columns[7].Read(reader), columns[8].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Assembly row /// /// Row ID /// /// /// /// /// /// internal uint ReadAssemblyRow(uint rid, out AssemblyHashAlgorithm hashAlgId, out Version version, out int attributes, out uint publicKey, out uint name) { var table = AssemblyTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; hashAlgId = (AssemblyHashAlgorithm)reader.ReadUInt32(); version = new Version(reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16()); attributes = reader.ReadInt32(); publicKey = columns[6].Read(reader); name = columns[7].Read(reader); return columns[8].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw AssemblyProcessor row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawAssemblyProcessorRow ReadAssemblyProcessorRow(uint rid) { var table = AssemblyProcessorTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); return new RawAssemblyProcessorRow(reader.ReadUInt32()); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw AssemblyOS row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawAssemblyOSRow ReadAssemblyOSRow(uint rid) { var table = AssemblyOSTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); return new RawAssemblyOSRow(reader.ReadUInt32(), reader.ReadUInt32(), reader.ReadUInt32()); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw AssemblyRef row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawAssemblyRefRow ReadAssemblyRefRow(uint rid) { var table = AssemblyRefTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawAssemblyRefRow(reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt32(), columns[5].Read(reader), columns[6].Read(reader), columns[7].Read(reader), columns[8].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw AssemblyRef row /// /// Row ID /// /// /// /// /// /// internal uint ReadAssemblyRefRow(uint rid, out Version version, out int attributes, out uint publicKeyOrToken, out uint name, out uint culture) { var table = AssemblyRefTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; version = new Version(reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16()); attributes = reader.ReadInt32(); publicKeyOrToken = columns[5].Read(reader); name = columns[6].Read(reader); culture = columns[7].Read(reader); return columns[8].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw AssemblyRefProcessor row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawAssemblyRefProcessorRow ReadAssemblyRefProcessorRow(uint rid) { var table = AssemblyRefProcessorTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawAssemblyRefProcessorRow(reader.ReadUInt32(), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw AssemblyRefOS row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawAssemblyRefOSRow ReadAssemblyRefOSRow(uint rid) { var table = AssemblyRefOSTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawAssemblyRefOSRow(reader.ReadUInt32(), reader.ReadUInt32(), reader.ReadUInt32(), columns[3].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw File row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawFileRow ReadFileRow(uint rid) { var table = FileTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawFileRow(reader.ReadUInt32(), columns[1].Read(reader), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw File row /// /// Row ID /// /// /// internal uint ReadFileRow(uint rid, out int attributes, out uint name) { var table = FileTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; attributes = reader.ReadInt32(); name = columns[1].Read(reader); return columns[2].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ExportedType row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawExportedTypeRow ReadExportedTypeRow(uint rid) { var table = ExportedTypeTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawExportedTypeRow(reader.ReadUInt32(), reader.ReadUInt32(), columns[2].Read(reader), columns[3].Read(reader), columns[4].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ExportedType row /// /// Row ID /// /// /// /// /// internal uint ReadExportedTypeRow(uint rid, out int attributes, out uint typeDefId, out uint name, out uint @namespace) { var table = ExportedTypeTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; attributes = reader.ReadInt32(); typeDefId = reader.ReadUInt32(); name = columns[2].Read(reader); @namespace = columns[3].Read(reader); return columns[4].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ManifestResource row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawManifestResourceRow ReadManifestResourceRow(uint rid) { var table = ManifestResourceTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawManifestResourceRow(reader.ReadUInt32(), reader.ReadUInt32(), columns[2].Read(reader), columns[3].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ManifestResource row /// /// Row ID /// /// /// /// internal uint ReadManifestResourceRow(uint rid, out uint offset, out int attributes, out uint name) { var table = ManifestResourceTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; offset = reader.ReadUInt32(); attributes = reader.ReadInt32(); name = columns[2].Read(reader); return columns[3].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw NestedClass row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawNestedClassRow ReadNestedClassRow(uint rid) { var table = NestedClassTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawNestedClassRow(columns[0].Read(reader), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw NestedClass row /// /// Row ID /// internal uint ReadNestedClassRow2(uint rid) { var table = NestedClassTable; if (table.IsInvalidRID(rid)) return 0; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; reader.Position += columns[0].Size; return columns[1].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw GenericParam row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawGenericParamRow ReadGenericParamRow(uint rid) { var table = GenericParamTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; if (columns.Count == 4) { return new RawGenericParamRow(reader.ReadUInt16(), reader.ReadUInt16(), columns[2].Read(reader), columns[3].Read(reader)); } return new RawGenericParamRow(reader.ReadUInt16(), reader.ReadUInt16(), columns[2].Read(reader), columns[3].Read(reader), columns[4].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw GenericParam row /// /// Row ID /// /// /// /// internal uint ReadGenericParamRow(uint rid, out ushort number, out int attributes, out uint name) { var table = GenericParamTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; number = reader.ReadUInt16(); attributes = reader.ReadUInt16(); reader.Position += columns[2].Size; name = columns[3].Read(reader); if (columns.Count == 4) return 0; return columns[4].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw MethodSpec row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawMethodSpecRow ReadMethodSpecRow(uint rid) { var table = MethodSpecTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawMethodSpecRow(columns[0].Read(reader), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw MethodSpec row /// /// Row ID /// /// internal uint ReadMethodSpecRow(uint rid, out uint method) { var table = MethodSpecTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; method = columns[0].Read(reader); return columns[1].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw GenericParamConstraint row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawGenericParamConstraintRow ReadGenericParamConstraintRow(uint rid) { var table = GenericParamConstraintTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawGenericParamConstraintRow(columns[0].Read(reader), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw GenericParamConstraint row /// /// Row ID /// internal uint ReadGenericParamConstraintRow2(uint rid) { var table = GenericParamConstraintTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; reader.Position += columns[0].Size; return columns[1].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw Document row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawDocumentRow ReadDocumentRow(uint rid) { var table = DocumentTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawDocumentRow(columns[0].Read(reader), columns[1].Read(reader), columns[2].Read(reader), columns[3].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } internal uint ReadDocumentRow2(uint rid, out uint name, out uint hashAlgorithm, out uint hash) { var table = DocumentTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; name = columns[0].Read(reader); hashAlgorithm = columns[1].Read(reader); hash = columns[2].Read(reader); return columns[3].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw MethodDebugInformation row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawMethodDebugInformationRow ReadMethodDebugInformationRow(uint rid) { var table = MethodDebugInformationTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawMethodDebugInformationRow(columns[0].Read(reader), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } internal uint ReadMethodDebugInformationRow2(uint rid, out uint document) { var table = MethodDebugInformationTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; document = columns[0].Read(reader); return columns[1].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw LocalScope row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawLocalScopeRow ReadLocalScopeRow(uint rid) { var table = LocalScopeTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawLocalScopeRow(columns[0].Read(reader), columns[1].Read(reader), columns[2].Read(reader), columns[3].Read(reader), reader.ReadUInt32(), reader.ReadUInt32()); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } internal uint ReadLocalScopeRow2(uint rid, out uint importScope, out uint variableList, out uint constantList, out uint startOffset) { var table = LocalScopeTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; reader.Position += columns[0].Size; importScope = columns[1].Read(reader); variableList = columns[2].Read(reader); constantList = columns[3].Read(reader); startOffset = reader.ReadUInt32(); return reader.ReadUInt32(); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw LocalVariable row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawLocalVariableRow ReadLocalVariableRow(uint rid) { var table = LocalVariableTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawLocalVariableRow(reader.ReadUInt16(), reader.ReadUInt16(), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } internal uint ReadLocalVariableRow2(uint rid, out ushort attributes, out ushort index) { var table = LocalVariableTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; attributes = reader.ReadUInt16(); index = reader.ReadUInt16(); return columns[2].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw LocalConstant row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawLocalConstantRow ReadLocalConstantRow(uint rid) { var table = LocalConstantTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawLocalConstantRow(columns[0].Read(reader), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } internal uint ReadLocalConstantRow2(uint rid, out uint name) { var table = LocalConstantTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; name = columns[0].Read(reader); return columns[1].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw ImportScope row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawImportScopeRow ReadImportScopeRow(uint rid) { var table = ImportScopeTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawImportScopeRow(columns[0].Read(reader), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } internal uint ReadImportScopeRow2(uint rid, out uint parent) { var table = ImportScopeTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; parent = columns[0].Read(reader); return columns[1].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw StateMachineMethod row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawStateMachineMethodRow ReadStateMachineMethodRow(uint rid) { var table = StateMachineMethodTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawStateMachineMethodRow(columns[0].Read(reader), columns[1].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } internal uint ReadStateMachineMethodRow2(uint rid) { var table = StateMachineMethodTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; reader.Position += columns[0].Size; return columns[1].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a raw CustomDebugInformation row /// /// Row ID /// The row or null if table doesn't exist or if is invalid public RawCustomDebugInformationRow ReadCustomDebugInformationRow(uint rid) { var table = CustomDebugInformationTable; if (table.IsInvalidRID(rid)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; return new RawCustomDebugInformationRow(columns[0].Read(reader), columns[1].Read(reader), columns[2].Read(reader)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } internal uint ReadCustomDebugInformationRow2(uint rid, out uint kind) { var table = CustomDebugInformationTable; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); var columns = table.TableInfo.Columns; reader.Position += columns[0].Size; kind = columns[1].Read(reader); return columns[2].Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads a column /// /// The table /// Row ID /// Column index in /// Result is put here or 0 if we return false /// true if we could read the column, false otherwise public bool ReadColumn(MDTable table, uint rid, int colIndex, out uint value) { return ReadColumn(table, rid, table.TableInfo.Columns[colIndex], out value); } /// /// Reads a column /// /// The table /// Row ID /// Column /// Result is put here or 0 if we return false /// true if we could read the column, false otherwise public bool ReadColumn(MDTable table, uint rid, ColumnInfo column, out uint value) { if (table.IsInvalidRID(rid)) { value = 0; return false; } var cr = columnReader; if (cr != null && cr.ReadColumn(table, rid, column, out value)) return true; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(table, rid); reader.Position += column.Offset; value = column.Read(reader); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif return true; } /// /// Reads a column /// /// The table /// Row ID /// Column /// Result is put here or 0 if we return false /// true if we could read the column, false otherwise internal bool ReadColumn_NoLock(MDTable table, uint rid, ColumnInfo column, out uint value) { if (table.IsInvalidRID(rid)) { value = 0; return false; } var cr = columnReader; if (cr != null && cr.ReadColumn(table, rid, column, out value)) return true; var reader = GetReader_NoLock(table, rid); reader.Position += column.Offset; value = column.Read(reader); return true; } } } dnlib-2.1_VS2010/src/DotNet/MD/USStream.cs000066400000000000000000000032271325033663500177070ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; namespace dnlib.DotNet.MD { /// /// Represents the #US stream /// public sealed class USStream : HeapStream { /// public USStream() { } /// public USStream(IImageStream imageStream, StreamHeader streamHeader) : base(imageStream, streamHeader) { } /// /// Reads a unicode string /// /// Offset of unicode string /// A string or null if is invalid public string Read(uint offset) { if (offset == 0) return string.Empty; if (!IsValidOffset(offset)) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var reader = GetReader_NoLock(offset); uint length; if (!reader.ReadCompressedUInt32(out length)) return null; if (reader.Position + length < length || reader.Position + length > reader.Length) return null; try { return reader.ReadString((int)(length / 2)); } catch (OutOfMemoryException) { throw; } catch { // It's possible that an exception is thrown when converting a char* to // a string. If so, return an empty string. return string.Empty; } #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Reads data just like , but returns an empty string if /// offset is invalid /// /// Offset of unicode string /// The string public string ReadNoNull(uint offset) { return Read(offset) ?? string.Empty; } } } dnlib-2.1_VS2010/src/DotNet/MDToken.cs000066400000000000000000000110621325033663500172010ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using dnlib.DotNet.MD; namespace dnlib.DotNet { /// /// MetaData token /// [DebuggerDisplay("{Table} {Rid}")] public struct MDToken : IEquatable, IComparable { /// /// Mask to get the rid from a raw metadata token /// public const uint RID_MASK = 0x00FFFFFF; /// /// Max rid value /// public const uint RID_MAX = RID_MASK; /// /// Number of bits to right shift a raw metadata token to get the table index /// public const int TABLE_SHIFT = 24; readonly uint token; /// /// Returns the table type /// public Table Table { get { return ToTable(token); } } /// /// Returns the row id /// public uint Rid { get { return ToRID(token); } } /// /// Returns the raw token /// public uint Raw { get { return token; } } /// /// Returns true if it's a null token /// public bool IsNull { get { return Rid == 0; } } /// /// Constructor /// /// Raw token public MDToken(uint token) { this.token = token; } /// /// Constructor /// /// Raw token public MDToken(int token) : this((uint)token) { } /// /// Constructor /// /// The table type /// Row id public MDToken(Table table, uint rid) : this(((uint)table << TABLE_SHIFT) | rid) { } /// /// Constructor /// /// The table type /// Row id public MDToken(Table table, int rid) : this(((uint)table << TABLE_SHIFT) | (uint)rid) { } /// /// Returns the rid (row ID) /// /// A raw metadata token /// A rid public static uint ToRID(uint token) { return token & RID_MASK; } /// /// Returns the rid (row ID) /// /// A raw metadata token /// A rid public static uint ToRID(int token) { return ToRID((uint)token); } /// /// Returns the table /// /// A raw metadata token /// A metadata table index public static Table ToTable(uint token) { return (Table)(token >> TABLE_SHIFT); } /// /// Returns the table /// /// A raw metadata token /// A metadata table index public static Table ToTable(int token) { return ToTable((uint)token); } /// /// Gets the token as a raw 32-bit signed integer /// public int ToInt32() { return (int)token; } /// /// Gets the token as a raw 32-bit unsigned integer /// public uint ToUInt32() { return token; } /// Overloaded operator public static bool operator ==(MDToken left, MDToken right) { return left.CompareTo(right) == 0; } /// Overloaded operator public static bool operator !=(MDToken left, MDToken right) { return left.CompareTo(right) != 0; } /// Overloaded operator public static bool operator <(MDToken left, MDToken right) { return left.CompareTo(right) < 0; } /// Overloaded operator public static bool operator >(MDToken left, MDToken right) { return left.CompareTo(right) > 0; } /// Overloaded operator public static bool operator <=(MDToken left, MDToken right) { return left.CompareTo(right) <= 0; } /// Overloaded operator public static bool operator >=(MDToken left, MDToken right) { return left.CompareTo(right) >= 0; } /// public int CompareTo(MDToken other) { return token.CompareTo(other.token); } /// public bool Equals(MDToken other) { return CompareTo(other) == 0; } /// public override bool Equals(object obj) { if (!(obj is MDToken)) return false; return Equals((MDToken)obj); } /// public override int GetHashCode() { return (int)token; } /// public override string ToString() { return string.Format("{0:X8}", token); } } } dnlib-2.1_VS2010/src/DotNet/ManifestResource.cs000066400000000000000000000204421325033663500211600ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the ManifestResource table /// [DebuggerDisplay("{Offset} {Name.String} {Implementation}")] public abstract class ManifestResource : IHasCustomAttribute, IHasCustomDebugInformation { /// /// The row id in its table /// protected uint rid; /// public MDToken MDToken { get { return new MDToken(Table.ManifestResource, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 18; } } /// /// From column ManifestResource.Offset /// public uint Offset { get { return offset; } set { offset = value; } } /// protected uint offset; /// /// From column ManifestResource.Flags /// public ManifestResourceAttributes Flags { get { return (ManifestResourceAttributes)attributes; } set { attributes = (int)value; } } /// Attributes protected int attributes; /// /// From column ManifestResource.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// From column ManifestResource.Implementation /// public IImplementation Implementation { get { return implementation; } set { implementation = value; } } /// protected IImplementation implementation; /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 18; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// /// Modify property: = /// ( & ) | . /// /// Value to AND /// Value to OR void ModifyAttributes(ManifestResourceAttributes andMask, ManifestResourceAttributes 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 attributes = (attributes & (int)andMask) | (int)orMask; #endif } /// /// Gets/sets the visibility /// public ManifestResourceAttributes Visibility { get { return (ManifestResourceAttributes)attributes & ManifestResourceAttributes.VisibilityMask; } set { ModifyAttributes(~ManifestResourceAttributes.VisibilityMask, value & ManifestResourceAttributes.VisibilityMask); } } /// /// true if is set /// public bool IsPublic { get { return ((ManifestResourceAttributes)attributes & ManifestResourceAttributes.VisibilityMask) == ManifestResourceAttributes.Public; } } /// /// true if is set /// public bool IsPrivate { get { return ((ManifestResourceAttributes)attributes & ManifestResourceAttributes.VisibilityMask) == ManifestResourceAttributes.Private; } } } /// /// A ManifestResource row created by the user and not present in the original .NET file /// public class ManifestResourceUser : ManifestResource { /// /// Default constructor /// public ManifestResourceUser() { } /// /// Constructor /// /// Name /// Implementation public ManifestResourceUser(UTF8String name, IImplementation implementation) : this(name, implementation, 0) { } /// /// Constructor /// /// Name /// Implementation /// Flags public ManifestResourceUser(UTF8String name, IImplementation implementation, ManifestResourceAttributes flags) : this(name, implementation, flags, 0) { } /// /// Constructor /// /// Name /// Implementation /// Flags /// Offset public ManifestResourceUser(UTF8String name, IImplementation implementation, ManifestResourceAttributes flags, uint offset) { this.name = name; this.implementation = implementation; this.attributes = (int)flags; this.offset = offset; } } /// /// Created from a row in the ManifestResource table /// sealed class ManifestResourceMD : ManifestResource, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.ManifestResource, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this ManifestResource row /// Row ID /// If is null /// If is invalid public ManifestResourceMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.ManifestResourceTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("ManifestResource rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; uint name; uint implementation = readerModule.TablesStream.ReadManifestResourceRow(origRid, out this.offset, out this.attributes, out name); this.name = readerModule.StringsStream.ReadNoNull(name); this.implementation = readerModule.ResolveImplementation(implementation); } } } dnlib-2.1_VS2010/src/DotNet/ManifestResourceAttributes.cs000066400000000000000000000007201325033663500232240ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// ManifestResource flags. See CorHdr.h/CorManifestResourceFlags /// [Flags] public enum ManifestResourceAttributes : uint { /// VisibilityMask = 0x0007, /// The Resource is exported from the Assembly. Public = 0x0001, /// The Resource is private to the Assembly. Private = 0x0002, } } dnlib-2.1_VS2010/src/DotNet/MarshalBlobReader.cs000066400000000000000000000134351325033663500212170ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; namespace dnlib.DotNet { /// /// Reads s /// public struct MarshalBlobReader : IDisposable { readonly ModuleDef module; readonly IBinaryReader reader; readonly GenericParamContext gpContext; /// /// Reads a from the #Blob heap /// /// Module /// Blob offset /// A new instance public static MarshalType Read(ModuleDefMD module, uint sig) { return Read(module, module.BlobStream.CreateStream(sig), new GenericParamContext()); } /// /// Reads a from the #Blob heap /// /// Module /// Blob offset /// Generic parameter context /// A new instance public static MarshalType Read(ModuleDefMD module, uint sig, GenericParamContext gpContext) { return Read(module, module.BlobStream.CreateStream(sig), gpContext); } /// /// Reads a from /// /// Owner module /// Marshal data /// A new instance public static MarshalType Read(ModuleDef module, byte[] data) { return Read(module, MemoryImageStream.Create(data), new GenericParamContext()); } /// /// Reads a from /// /// Owner module /// Marshal data /// Generic parameter context /// A new instance public static MarshalType Read(ModuleDef module, byte[] data, GenericParamContext gpContext) { return Read(module, MemoryImageStream.Create(data), gpContext); } /// /// Reads a from /// /// Owner module /// A reader that will be owned by us /// A new instance public static MarshalType Read(ModuleDef module, IBinaryReader reader) { return Read(module, reader, new GenericParamContext()); } /// /// Reads a from /// /// Owner module /// A reader that will be owned by us /// Generic parameter context /// A new instance public static MarshalType Read(ModuleDef module, IBinaryReader reader, GenericParamContext gpContext) { using (var marshalReader = new MarshalBlobReader(module, reader, gpContext)) return marshalReader.Read(); } MarshalBlobReader(ModuleDef module, IBinaryReader reader, GenericParamContext gpContext) { this.module = module; this.reader = reader; this.gpContext = gpContext; } MarshalType Read() { MarshalType returnValue; try { var nativeType = (NativeType)reader.ReadByte(); NativeType nt; int size; switch (nativeType) { case NativeType.FixedSysString: size = CanRead() ? (int)reader.ReadCompressedUInt32() : -1; returnValue = new FixedSysStringMarshalType(size); break; case NativeType.SafeArray: var vt = CanRead() ? (VariantType)reader.ReadCompressedUInt32() : VariantType.NotInitialized; var udtName = CanRead() ? ReadUTF8String() : null; var udtRef = (object)udtName == null ? null : TypeNameParser.ParseReflection(module, UTF8String.ToSystemStringOrEmpty(udtName), null, gpContext); returnValue = new SafeArrayMarshalType(vt, udtRef); break; case NativeType.FixedArray: size = CanRead() ? (int)reader.ReadCompressedUInt32() : -1; nt = CanRead() ? (NativeType)reader.ReadCompressedUInt32() : NativeType.NotInitialized; returnValue = new FixedArrayMarshalType(size, nt); break; case NativeType.Array: nt = CanRead() ? (NativeType)reader.ReadCompressedUInt32() : NativeType.NotInitialized; int paramNum = CanRead() ? (int)reader.ReadCompressedUInt32() : -1; size = CanRead() ? (int)reader.ReadCompressedUInt32() : -1; int flags = CanRead() ? (int)reader.ReadCompressedUInt32() : -1; returnValue = new ArrayMarshalType(nt, paramNum, size, flags); break; case NativeType.CustomMarshaler: var guid = ReadUTF8String(); var nativeTypeName = ReadUTF8String(); var custMarshalerName = ReadUTF8String(); var cmRef = TypeNameParser.ParseReflection(module, UTF8String.ToSystemStringOrEmpty(custMarshalerName), new CAAssemblyRefFinder(module), gpContext); var cookie = ReadUTF8String(); returnValue = new CustomMarshalType(guid, nativeTypeName, cmRef, cookie); break; case NativeType.IUnknown: case NativeType.IDispatch: case NativeType.IntF: int iidParamIndex = CanRead() ? (int)reader.ReadCompressedUInt32() : -1; return new InterfaceMarshalType(nativeType, iidParamIndex); default: returnValue = new MarshalType(nativeType); break; } } catch { returnValue = new RawMarshalType(reader.ReadAllBytes()); } return returnValue; } bool CanRead() { return reader.Position < reader.Length; } UTF8String ReadUTF8String() { uint len = reader.ReadCompressedUInt32(); return len == 0 ? UTF8String.Empty : new UTF8String(reader.ReadBytes((int)len)); } /// public void Dispose() { if (reader != null) reader.Dispose(); } } } dnlib-2.1_VS2010/src/DotNet/MarshalType.cs000066400000000000000000000324071325033663500201370ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// Base class of all marshal types /// public class MarshalType { /// /// The native type /// protected readonly NativeType nativeType; /// /// Gets the /// public NativeType NativeType { get { return nativeType; } } /// /// Constructor /// /// Native type public MarshalType(NativeType nativeType) { this.nativeType = nativeType; } /// public override string ToString() { return nativeType.ToString(); } } /// /// Contains the raw marshal blob data /// public sealed class RawMarshalType : MarshalType { byte[] data; /// /// Gets/sets the raw data /// public byte[] Data { get { return data; } set { data = value; } } /// /// Constructor /// /// Raw data public RawMarshalType(byte[] data) : base(NativeType.RawBlob) { this.data = data; } } /// /// A marshal type /// public sealed class FixedSysStringMarshalType : MarshalType { int size; /// /// Gets/sets the size /// public int Size { get { return size; } set { size = value; } } /// /// true if is valid /// public bool IsSizeValid { get { return size >= 0; } } /// /// Default constructor /// public FixedSysStringMarshalType() : this(-1) { } /// /// Constructor /// /// Size public FixedSysStringMarshalType(int size) : base(NativeType.FixedSysString) { this.size = size; } /// public override string ToString() { if (IsSizeValid) return string.Format("{0} ({1})", nativeType, size); return string.Format("{0} ()", nativeType); } } /// /// A marshal type /// public sealed class SafeArrayMarshalType : MarshalType { VariantType vt; ITypeDefOrRef userDefinedSubType; /// /// Gets/sets the variant type /// public VariantType VariantType { get { return vt; } set { vt = value; } } /// /// Gets/sets the user-defined sub type (it's usually null) /// public ITypeDefOrRef UserDefinedSubType { get { return userDefinedSubType; } set { userDefinedSubType = value; } } /// /// true if is valid /// public bool IsVariantTypeValid { get { return vt != VariantType.NotInitialized; } } /// /// true if is valid /// public bool IsUserDefinedSubTypeValid { get { return userDefinedSubType != null; } } /// /// Default constructor /// public SafeArrayMarshalType() : this(VariantType.NotInitialized, null) { } /// /// Constructor /// /// Variant type public SafeArrayMarshalType(VariantType vt) : this(vt, null) { } /// /// Constructor /// /// User-defined sub type public SafeArrayMarshalType(ITypeDefOrRef userDefinedSubType) : this(VariantType.NotInitialized, userDefinedSubType) { } /// /// Constructor /// /// Variant type /// User-defined sub type public SafeArrayMarshalType(VariantType vt, ITypeDefOrRef userDefinedSubType) : base(NativeType.SafeArray) { this.vt = vt; this.userDefinedSubType = userDefinedSubType; } /// public override string ToString() { var udt = userDefinedSubType; if (udt != null) return string.Format("{0} ({1}, {2})", nativeType, vt, udt); return string.Format("{0} ({1})", nativeType, vt); } } /// /// A marshal type /// public sealed class FixedArrayMarshalType : MarshalType { int size; NativeType elementType; /// /// Gets/sets the element type /// public NativeType ElementType { get { return elementType; } set { elementType = value; } } /// /// Gets/sets the size /// public int Size { get { return size; } set { size = value; } } /// /// true if is valid /// public bool IsElementTypeValid { get { return elementType != NativeType.NotInitialized; } } /// /// true if is valid /// public bool IsSizeValid { get { return size >= 0; } } /// /// Default constructor /// public FixedArrayMarshalType() : this(0) { } /// /// Constructor /// /// Size public FixedArrayMarshalType(int size) : this(size, NativeType.NotInitialized) { } /// /// Constructor /// /// Size /// Element type public FixedArrayMarshalType(int size, NativeType elementType) : base(NativeType.FixedArray) { this.size = size; this.elementType = elementType; } /// public override string ToString() { return string.Format("{0} ({1}, {2})", nativeType, size, elementType); } } /// /// A marshal type /// public sealed class ArrayMarshalType : MarshalType { NativeType elementType; int paramNum; int numElems; int flags; /// /// Gets/sets the element type /// public NativeType ElementType { get { return elementType; } set { elementType = value; } } /// /// Gets/sets the parameter number /// public int ParamNumber { get { return paramNum; } set { paramNum = value; } } /// /// Gets/sets the size of the array /// public int Size { get { return numElems; } set { numElems = value; } } /// /// Gets/sets the flags /// public int Flags { get { return flags; } set { flags = value; } } /// /// true if is valid /// public bool IsElementTypeValid { get { return elementType != NativeType.NotInitialized; } } /// /// true if is valid /// public bool IsParamNumberValid { get { return paramNum >= 0; } } /// /// true if is valid /// public bool IsSizeValid { get { return numElems >= 0; } } /// /// true if is valid /// public bool IsFlagsValid { get { return flags >= 0; } } const int ntaSizeParamIndexSpecified = 1; /// /// true if ntaSizeParamIndexSpecified bit is set, false if it's not /// set or if is invalid. /// public bool IsSizeParamIndexSpecified { get { return IsFlagsValid && (flags & ntaSizeParamIndexSpecified) != 0; } } /// /// true if ntaSizeParamIndexSpecified bit is not set, false if it's /// set or if is invalid. /// public bool IsSizeParamIndexNotSpecified { get { return IsFlagsValid && (flags & ntaSizeParamIndexSpecified) == 0; } } /// /// Default constructor /// public ArrayMarshalType() : this(NativeType.NotInitialized, -1, -1, -1) { } /// /// Constructor /// /// Element type public ArrayMarshalType(NativeType elementType) : this(elementType, -1, -1, -1) { } /// /// Constructor /// /// Element type /// Parameter number public ArrayMarshalType(NativeType elementType, int paramNum) : this(elementType, paramNum, -1, -1) { } /// /// Constructor /// /// Element type /// Parameter number /// Number of elements public ArrayMarshalType(NativeType elementType, int paramNum, int numElems) : this(elementType, paramNum, numElems, -1) { } /// /// Constructor /// /// Element type /// Parameter number /// Number of elements /// Flags public ArrayMarshalType(NativeType elementType, int paramNum, int numElems, int flags) : base(NativeType.Array) { this.elementType = elementType; this.paramNum = paramNum; this.numElems = numElems; this.flags = flags; } /// public override string ToString() { return string.Format("{0} ({1}, {2}, {3}, {4})", nativeType, elementType, paramNum, numElems, flags); } } /// /// A marshal type /// public sealed class CustomMarshalType : MarshalType { UTF8String guid; UTF8String nativeTypeName; ITypeDefOrRef custMarshaler; UTF8String cookie; /// /// Gets/sets the GUID string /// public UTF8String Guid { get { return guid; } set { guid = value; } } /// /// Gets/sets the native type name string /// public UTF8String NativeTypeName { get { return nativeTypeName; } set { nativeTypeName = value; } } /// /// Gets/sets the custom marshaler /// public ITypeDefOrRef CustomMarshaler { get { return custMarshaler; } set { custMarshaler = value; } } /// /// Gets/sets the cookie string /// public UTF8String Cookie { get { return cookie; } set { cookie = value; } } /// /// Default constructor /// public CustomMarshalType() : this(null, null, null, null) { } /// /// Constructor /// /// GUID string public CustomMarshalType(UTF8String guid) : this(guid, null, null, null) { } /// /// Constructor /// /// GUID string /// Native type name string public CustomMarshalType(UTF8String guid, UTF8String nativeTypeName) : this(guid, nativeTypeName, null, null) { } /// /// Constructor /// /// GUID string /// Native type name string /// Custom marshaler name string public CustomMarshalType(UTF8String guid, UTF8String nativeTypeName, ITypeDefOrRef custMarshaler) : this(guid, nativeTypeName, custMarshaler, null) { } /// /// Constructor /// /// GUID string /// Native type name string /// Custom marshaler name string /// Cookie string public CustomMarshalType(UTF8String guid, UTF8String nativeTypeName, ITypeDefOrRef custMarshaler, UTF8String cookie) : base(NativeType.CustomMarshaler) { this.guid = guid; this.nativeTypeName = nativeTypeName; this.custMarshaler = custMarshaler; this.cookie = cookie; } /// public override string ToString() { return string.Format("{0} ({1}, {2}, {3}, {4})", nativeType, guid, nativeTypeName, custMarshaler, cookie); } } /// /// A , or a /// marshal type /// public sealed class InterfaceMarshalType : MarshalType { int iidParamIndex; /// /// Gets/sets the IID parameter index /// public int IidParamIndex { get { return iidParamIndex; } set { iidParamIndex = value; } } /// /// true if is valid /// public bool IsIidParamIndexValid { get { return iidParamIndex >= 0; } } /// /// Constructor /// /// Native type public InterfaceMarshalType(NativeType nativeType) : this(nativeType, -1) { } /// /// Constructor /// /// Native type /// IID parameter index public InterfaceMarshalType(NativeType nativeType, int iidParamIndex) : base(nativeType) { if (nativeType != NativeType.IUnknown && nativeType != NativeType.IDispatch && nativeType != NativeType.IntF) throw new ArgumentException("Invalid nativeType"); this.iidParamIndex = iidParamIndex; } /// public override string ToString() { return string.Format("{0} ({1})", nativeType, iidParamIndex); } } } dnlib-2.1_VS2010/src/DotNet/MemberFinder.cs000066400000000000000000000414521325033663500202450ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using dnlib.DotNet.Emit; namespace dnlib.DotNet { /// /// Finds types, fields, methods, etc in a module. If nothing has been added to the module, it's /// faster to call ResolveMethodDef(), ResolveTypeRef() etc. /// public class MemberFinder { enum ObjectType { Unknown, EventDef, FieldDef, GenericParam, MemberRef, MethodDef, MethodSpec, PropertyDef, TypeDef, TypeRef, TypeSig, TypeSpec, ExportedType, } /// /// All found s /// public readonly Dictionary CustomAttributes = new Dictionary(); /// /// All found s /// public readonly Dictionary EventDefs = new Dictionary(); /// /// All found s /// public readonly Dictionary FieldDefs = new Dictionary(); /// /// All found s /// public readonly Dictionary GenericParams = new Dictionary(); /// /// All found s /// public readonly Dictionary MemberRefs = new Dictionary(); /// /// All found s /// public readonly Dictionary MethodDefs = new Dictionary(); /// /// All found s /// public readonly Dictionary MethodSpecs = new Dictionary(); /// /// All found s /// public readonly Dictionary PropertyDefs = new Dictionary(); /// /// All found s /// public readonly Dictionary TypeDefs = new Dictionary(); /// /// All found s /// public readonly Dictionary TypeRefs = new Dictionary(); /// /// All found s /// public readonly Dictionary TypeSigs = new Dictionary(); /// /// All found s /// public readonly Dictionary TypeSpecs = new Dictionary(); /// /// All found s /// public readonly Dictionary ExportedTypes = new Dictionary(); Stack objectStack; ModuleDef validModule; /// /// Finds all types, fields, etc /// /// The module to scan /// Itself public MemberFinder FindAll(ModuleDef module) { validModule = module; // This needs to be big. About 2048 entries should be enough for most though... objectStack = new Stack(0x1000); Add(module); ProcessAll(); objectStack = null; return this; } void Push(object mr) { if (mr == null) return; objectStack.Push(mr); } void ProcessAll() { while (objectStack.Count > 0) { var o = objectStack.Pop(); switch (GetObjectType(o)) { case ObjectType.Unknown: break; case ObjectType.EventDef: Add((EventDef)o); break; case ObjectType.FieldDef: Add((FieldDef)o); break; case ObjectType.GenericParam: Add((GenericParam)o); break; case ObjectType.MemberRef: Add((MemberRef)o); break; case ObjectType.MethodDef: Add((MethodDef)o); break; case ObjectType.MethodSpec: Add((MethodSpec)o); break; case ObjectType.PropertyDef: Add((PropertyDef)o); break; case ObjectType.TypeDef: Add((TypeDef)o); break; case ObjectType.TypeRef: Add((TypeRef)o); break; case ObjectType.TypeSig: Add((TypeSig)o); break; case ObjectType.TypeSpec: Add((TypeSpec)o); break; case ObjectType.ExportedType: Add((ExportedType)o); break; default: throw new InvalidOperationException(string.Format("Unknown type: {0}", o.GetType())); } } } readonly Dictionary toObjectType = new Dictionary(); ObjectType GetObjectType(object o) { if (o == null) return ObjectType.Unknown; var type = o.GetType(); ObjectType mrType; if (toObjectType.TryGetValue(type, out mrType)) return mrType; mrType = GetObjectType2(o); toObjectType[type] = mrType; return mrType; } static ObjectType GetObjectType2(object o) { if (o is EventDef) return ObjectType.EventDef; if (o is FieldDef) return ObjectType.FieldDef; if (o is GenericParam) return ObjectType.GenericParam; if (o is MemberRef) return ObjectType.MemberRef; if (o is MethodDef) return ObjectType.MethodDef; if (o is MethodSpec) return ObjectType.MethodSpec; if (o is PropertyDef) return ObjectType.PropertyDef; if (o is TypeDef) return ObjectType.TypeDef; if (o is TypeRef) return ObjectType.TypeRef; if (o is TypeSig) return ObjectType.TypeSig; if (o is TypeSpec) return ObjectType.TypeSpec; if (o is ExportedType) return ObjectType.ExportedType; return ObjectType.Unknown; } void Add(ModuleDef mod) { Push(mod.ManagedEntryPoint); Add(mod.CustomAttributes); Add(mod.Types); Add(mod.ExportedTypes); if (mod.IsManifestModule) Add(mod.Assembly); Add(mod.VTableFixups); } void Add(VTableFixups fixups) { if (fixups == null) return; foreach (var fixup in fixups) { foreach (var method in fixup) Push(method); } } void Add(AssemblyDef asm) { if (asm == null) return; Add(asm.DeclSecurities); Add(asm.CustomAttributes); } void Add(CallingConventionSig sig) { if (sig == null) return; var fs = sig as FieldSig; if (fs != null) { Add(fs); return; } var mbs = sig as MethodBaseSig; if (mbs != null) { Add(mbs); return; } var ls = sig as LocalSig; if (ls != null) { Add(ls); return; } var gims = sig as GenericInstMethodSig; if (gims != null) { Add(gims); return; } } void Add(FieldSig sig) { if (sig == null) return; Add(sig.Type); } void Add(MethodBaseSig sig) { if (sig == null) return; Add(sig.RetType); Add(sig.Params); Add(sig.ParamsAfterSentinel); } void Add(LocalSig sig) { if (sig == null) return; Add(sig.Locals); } void Add(GenericInstMethodSig sig) { if (sig == null) return; Add(sig.GenericArguments); } void Add(IEnumerable cas) { if (cas == null) return; foreach (var ca in cas) Add(ca); } void Add(CustomAttribute ca) { if (ca == null || CustomAttributes.ContainsKey(ca)) return; CustomAttributes[ca] = true; Push(ca.Constructor); Add(ca.ConstructorArguments); Add(ca.NamedArguments); } void Add(IEnumerable args) { if (args == null) return; foreach (var arg in args) Add(arg); } void Add(CAArgument arg) { // It's a struct so can't be null Add(arg.Type); } void Add(IEnumerable args) { if (args == null) return; foreach (var arg in args) Add(arg); } void Add(CANamedArgument arg) { if (arg == null) return; Add(arg.Type); Add(arg.Argument); } void Add(IEnumerable decls) { if (decls == null) return; foreach (var decl in decls) Add(decl); } void Add(DeclSecurity decl) { if (decl == null) return; Add(decl.SecurityAttributes); Add(decl.CustomAttributes); } void Add(IEnumerable secAttrs) { if (secAttrs == null) return; foreach (var secAttr in secAttrs) Add(secAttr); } void Add(SecurityAttribute secAttr) { if (secAttr == null) return; Add(secAttr.AttributeType); Add(secAttr.NamedArguments); } void Add(ITypeDefOrRef tdr) { var td = tdr as TypeDef; if (td != null) { Add(td); return; } var tr = tdr as TypeRef; if (tr != null) { Add(tr); return; } var ts = tdr as TypeSpec; if (ts != null) { Add(ts); return; } } void Add(IEnumerable eds) { if (eds == null) return; foreach (var ed in eds) Add(ed); } void Add(EventDef ed) { if (ed == null || EventDefs.ContainsKey(ed)) return; if (ed.DeclaringType != null && ed.DeclaringType.Module != validModule) return; EventDefs[ed] = true; Push(ed.EventType); Add(ed.CustomAttributes); Add(ed.AddMethod); Add(ed.InvokeMethod); Add(ed.RemoveMethod); Add(ed.OtherMethods); Add(ed.DeclaringType); } void Add(IEnumerable fds) { if (fds == null) return; foreach (var fd in fds) Add(fd); } void Add(FieldDef fd) { if (fd == null || FieldDefs.ContainsKey(fd)) return; if (fd.DeclaringType != null && fd.DeclaringType.Module != validModule) return; FieldDefs[fd] = true; Add(fd.CustomAttributes); Add(fd.Signature); Add(fd.DeclaringType); Add(fd.MarshalType); } void Add(IEnumerable gps) { if (gps == null) return; foreach (var gp in gps) Add(gp); } void Add(GenericParam gp) { if (gp == null || GenericParams.ContainsKey(gp)) return; GenericParams[gp] = true; Push(gp.Owner); Push(gp.Kind); Add(gp.GenericParamConstraints); Add(gp.CustomAttributes); } void Add(IEnumerable gpcs) { if (gpcs == null) return; foreach (var gpc in gpcs) Add(gpc); } void Add(GenericParamConstraint gpc) { if (gpc == null) return; Add(gpc.Owner); Push(gpc.Constraint); Add(gpc.CustomAttributes); } void Add(MemberRef mr) { if (mr == null || MemberRefs.ContainsKey(mr)) return; if (mr.Module != validModule) return; MemberRefs[mr] = true; Push(mr.Class); Add(mr.Signature); Add(mr.CustomAttributes); } void Add(IEnumerable methods) { if (methods == null) return; foreach (var m in methods) Add(m); } void Add(MethodDef md) { if (md == null || MethodDefs.ContainsKey(md)) return; if (md.DeclaringType != null && md.DeclaringType.Module != validModule) return; MethodDefs[md] = true; Add(md.Signature); Add(md.ParamDefs); Add(md.GenericParameters); Add(md.DeclSecurities); Add(md.MethodBody); Add(md.CustomAttributes); Add(md.Overrides); Add(md.DeclaringType); } void Add(MethodBody mb) { var cb = mb as CilBody; if (cb != null) Add(cb); } void Add(CilBody cb) { if (cb == null) return; Add(cb.Instructions); Add(cb.ExceptionHandlers); Add(cb.Variables); } void Add(IEnumerable instrs) { if (instrs == null) return; foreach (var instr in instrs) { if (instr == null) continue; switch (instr.OpCode.OperandType) { case OperandType.InlineTok: case OperandType.InlineType: case OperandType.InlineMethod: case OperandType.InlineField: Push(instr.Operand); break; case OperandType.InlineSig: Add(instr.Operand as CallingConventionSig); break; case OperandType.InlineVar: case OperandType.ShortInlineVar: var local = instr.Operand as Local; if (local != null) { Add(local); break; } var arg = instr.Operand as Parameter; if (arg != null) { Add(arg); break; } break; } } } void Add(IEnumerable ehs) { if (ehs == null) return; foreach (var eh in ehs) Push(eh.CatchType); } void Add(IEnumerable locals) { if (locals == null) return; foreach (var local in locals) Add(local); } void Add(Local local) { if (local == null) return; Add(local.Type); } void Add(IEnumerable ps) { if (ps == null) return; foreach (var p in ps) Add(p); } void Add(Parameter param) { if (param == null) return; Add(param.Type); Add(param.Method); } void Add(IEnumerable pds) { if (pds == null) return; foreach (var pd in pds) Add(pd); } void Add(ParamDef pd) { if (pd == null) return; Add(pd.DeclaringMethod); Add(pd.CustomAttributes); Add(pd.MarshalType); } void Add(MarshalType mt) { if (mt == null) return; switch (mt.NativeType) { case NativeType.SafeArray: Add(((SafeArrayMarshalType)mt).UserDefinedSubType); break; case NativeType.CustomMarshaler: Add(((CustomMarshalType)mt).CustomMarshaler); break; } } void Add(IEnumerable mos) { if (mos == null) return; foreach (var mo in mos) Add(mo); } void Add(MethodOverride mo) { // It's a struct so can't be null Push(mo.MethodBody); Push(mo.MethodDeclaration); } void Add(MethodSpec ms) { if (ms == null || MethodSpecs.ContainsKey(ms)) return; if (ms.Method != null && ms.Method.DeclaringType != null && ms.Method.DeclaringType.Module != validModule) return; MethodSpecs[ms] = true; Push(ms.Method); Add(ms.Instantiation); Add(ms.CustomAttributes); } void Add(IEnumerable pds) { if (pds == null) return; foreach (var pd in pds) Add(pd); } void Add(PropertyDef pd) { if (pd == null || PropertyDefs.ContainsKey(pd)) return; if (pd.DeclaringType != null && pd.DeclaringType.Module != validModule) return; PropertyDefs[pd] = true; Add(pd.Type); Add(pd.CustomAttributes); Add(pd.GetMethods); Add(pd.SetMethods); Add(pd.OtherMethods); Add(pd.DeclaringType); } void Add(IEnumerable tds) { if (tds == null) return; foreach (var td in tds) Add(td); } void Add(TypeDef td) { if (td == null || TypeDefs.ContainsKey(td)) return; if (td.Module != validModule) return; TypeDefs[td] = true; Push(td.BaseType); Add(td.Fields); Add(td.Methods); Add(td.GenericParameters); Add(td.Interfaces); Add(td.DeclSecurities); Add(td.DeclaringType); Add(td.Events); Add(td.Properties); Add(td.NestedTypes); Add(td.CustomAttributes); } void Add(IEnumerable iis) { if (iis == null) return; foreach (var ii in iis) Add(ii); } void Add(InterfaceImpl ii) { if (ii == null) return; Push(ii.Interface); Add(ii.CustomAttributes); } void Add(TypeRef tr) { if (tr == null || TypeRefs.ContainsKey(tr)) return; if (tr.Module != validModule) return; TypeRefs[tr] = true; Push(tr.ResolutionScope); Add(tr.CustomAttributes); } void Add(IEnumerable tss) { if (tss == null) return; foreach (var ts in tss) Add(ts); } void Add(TypeSig ts) { if (ts == null || TypeSigs.ContainsKey(ts)) return; if (ts.Module != validModule) return; TypeSigs[ts] = true; for (; ts != null; ts = ts.Next) { switch (ts.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.ValueType: case ElementType.Class: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: var tdrs = (TypeDefOrRefSig)ts; Push(tdrs.TypeDefOrRef); break; case ElementType.FnPtr: var fps = (FnPtrSig)ts; Add(fps.Signature); break; case ElementType.GenericInst: var gis = (GenericInstSig)ts; Add(gis.GenericType); Add(gis.GenericArguments); break; case ElementType.CModReqd: case ElementType.CModOpt: var ms = (ModifierSig)ts; Push(ms.Modifier); break; case ElementType.End: case ElementType.Ptr: case ElementType.ByRef: case ElementType.Var: case ElementType.Array: case ElementType.ValueArray: case ElementType.R: case ElementType.SZArray: case ElementType.MVar: case ElementType.Internal: case ElementType.Module: case ElementType.Sentinel: case ElementType.Pinned: default: break; } } } void Add(TypeSpec ts) { if (ts == null || TypeSpecs.ContainsKey(ts)) return; if (ts.Module != validModule) return; TypeSpecs[ts] = true; Add(ts.TypeSig); Add(ts.CustomAttributes); } void Add(IEnumerable ets) { if (ets == null) return; foreach (var et in ets) Add(et); } void Add(ExportedType et) { if (et == null || ExportedTypes.ContainsKey(et)) return; if (et.Module != validModule) return; ExportedTypes[et] = true; Add(et.CustomAttributes); Push(et.Implementation); } } } dnlib-2.1_VS2010/src/DotNet/MemberMDInitializer.cs000066400000000000000000000013571325033663500215420ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using dnlib.Threading; namespace dnlib.DotNet { /// /// Methods to load properties to make sure they're initialized /// static class MemberMDInitializer { /// /// Read every collection element /// /// Collection element type /// Collection public static void Initialize(IEnumerable coll) { if (coll == null) return; foreach (var c in coll.GetSafeEnumerable()) { } } /// /// Load the object instance /// /// The value (ignored) public static void Initialize(object o) { } } } dnlib-2.1_VS2010/src/DotNet/MemberRef.cs000066400000000000000000000400521325033663500175450ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the MemberRef table /// public abstract class MemberRef : IHasCustomAttribute, IMethodDefOrRef, ICustomAttributeType, IField, IContainsGenericParameter, IHasCustomDebugInformation { /// /// The row id in its table /// protected uint rid; /// /// The owner module /// protected ModuleDef module; /// public MDToken MDToken { get { return new MDToken(Table.MemberRef, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 6; } } /// public int MethodDefOrRefTag { get { return 1; } } /// public int CustomAttributeTypeTag { get { return 3; } } /// /// From column MemberRef.Class /// public IMemberRefParent Class { get { return @class; } set { @class = value; } } /// protected IMemberRefParent @class; /// /// From column MemberRef.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// From column MemberRef.Signature /// public CallingConventionSig Signature { get { return signature; } set { signature = value; } } /// protected CallingConventionSig signature; /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 6; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// public ITypeDefOrRef DeclaringType { get { var owner = @class; var tdr = owner as ITypeDefOrRef; if (tdr != null) return tdr; var method = owner as MethodDef; if (method != null) return method.DeclaringType; var mr = owner as ModuleRef; if (mr != null) { var tr = GetGlobalTypeRef(mr); if (module != null) return module.UpdateRowId(tr); return tr; } return null; } } TypeRefUser GetGlobalTypeRef(ModuleRef mr) { if (module == null) return CreateDefaultGlobalTypeRef(mr); var globalType = module.GlobalType; if (globalType != null && new SigComparer().Equals(module, mr)) return new TypeRefUser(module, globalType.Namespace, globalType.Name, mr); var asm = module.Assembly; if (asm == null) return CreateDefaultGlobalTypeRef(mr); var mod = asm.FindModule(mr.Name); if (mod == null) return CreateDefaultGlobalTypeRef(mr); globalType = mod.GlobalType; if (globalType == null) return CreateDefaultGlobalTypeRef(mr); return new TypeRefUser(module, globalType.Namespace, globalType.Name, mr); } TypeRefUser CreateDefaultGlobalTypeRef(ModuleRef mr) { var tr = new TypeRefUser(module, string.Empty, "", mr); if (module != null) module.UpdateRowId(tr); return tr; } bool IIsTypeOrMethod.IsType { get { return false; } } bool IIsTypeOrMethod.IsMethod { get { return IsMethodRef; } } bool IMemberRef.IsField { get { return IsFieldRef; } } bool IMemberRef.IsTypeSpec { get { return false; } } bool IMemberRef.IsTypeRef { get { return false; } } bool IMemberRef.IsTypeDef { get { return false; } } bool IMemberRef.IsMethodSpec { get { return false; } } bool IMemberRef.IsMethodDef { get { return false; } } bool IMemberRef.IsMemberRef { get { return true; } } bool IMemberRef.IsFieldDef { get { return false; } } bool IMemberRef.IsPropertyDef { get { return false; } } bool IMemberRef.IsEventDef { get { return false; } } bool IMemberRef.IsGenericParam { get { return false; } } /// /// true if this is a method reference ( != null) /// public bool IsMethodRef { get { return MethodSig != null; } } /// /// true if this is a field reference ( != null) /// public bool IsFieldRef { get { return FieldSig != null; } } /// /// Gets/sets the method sig /// public MethodSig MethodSig { get { return signature as MethodSig; } set { signature = value; } } /// /// Gets/sets the field sig /// public FieldSig FieldSig { get { return signature as FieldSig; } set { signature = value; } } /// public ModuleDef Module { get { return module; } } /// /// true if the method has a hidden 'this' parameter /// public bool HasThis { get { var ms = MethodSig; return ms == null ? false : ms.HasThis; } } /// /// true if the method has an explicit 'this' parameter /// public bool ExplicitThis { get { var ms = MethodSig; return ms == null ? false : ms.ExplicitThis; } } /// /// Gets the calling convention /// public CallingConvention CallingConvention { get { var ms = MethodSig; return ms == null ? 0 : ms.CallingConvention & CallingConvention.Mask; } } /// /// Gets/sets the method return type /// public TypeSig ReturnType { get { var ms = MethodSig; return ms == null ? null : ms.RetType; } set { var ms = MethodSig; if (ms != null) ms.RetType = value; } } /// int IGenericParameterProvider.NumberOfGenericParameters { get { var sig = MethodSig; return sig == null ? 0 : (int)sig.GenParamCount; } } /// /// Gets the full name /// public string FullName { get { var parent = @class; IList typeGenArgs = null; if (parent is TypeSpec) { var sig = ((TypeSpec)parent).TypeSig as GenericInstSig; if (sig != null) typeGenArgs = sig.GenericArguments; } var methodSig = MethodSig; if (methodSig != null) return FullNameCreator.MethodFullName(GetDeclaringTypeFullName(parent), name, methodSig, typeGenArgs, null, null, null); var fieldSig = FieldSig; if (fieldSig != null) return FullNameCreator.FieldFullName(GetDeclaringTypeFullName(parent), name, fieldSig, typeGenArgs, null); return string.Empty; } } /// /// Get the declaring type's full name /// /// Full name or null if there's no declaring type public string GetDeclaringTypeFullName() { return GetDeclaringTypeFullName(@class); } string GetDeclaringTypeFullName(IMemberRefParent parent) { if (parent == null) return null; if (parent is ITypeDefOrRef) return ((ITypeDefOrRef)parent).FullName; if (parent is ModuleRef) return string.Format("[module:{0}]", ((ModuleRef)parent).ToString()); if (parent is MethodDef) { var declaringType = ((MethodDef)parent).DeclaringType; return declaringType == null ? null : declaringType.FullName; } return null; // Should never be reached } /// /// Resolves the method/field /// /// A or a instance or null /// if it couldn't be resolved. public IMemberForwarded Resolve() { if (module == null) return null; return module.Context.Resolver.Resolve(this); } /// /// Resolves the method/field /// /// A or a instance /// If the method/field couldn't be resolved public IMemberForwarded ResolveThrow() { var memberDef = Resolve(); if (memberDef != null) return memberDef; throw new MemberRefResolveException(string.Format("Could not resolve method/field: {0} ({1})", this, this.GetDefinitionAssembly())); } /// /// Resolves the field /// /// A instance or null if it couldn't be resolved. public FieldDef ResolveField() { return Resolve() as FieldDef; } /// /// Resolves the field /// /// A instance /// If the field couldn't be resolved public FieldDef ResolveFieldThrow() { var field = ResolveField(); if (field != null) return field; throw new MemberRefResolveException(string.Format("Could not resolve field: {0} ({1})", this, this.GetDefinitionAssembly())); } /// /// Resolves the method /// /// A instance or null if it couldn't be resolved. public MethodDef ResolveMethod() { return Resolve() as MethodDef; } /// /// Resolves the method /// /// A instance /// If the method couldn't be resolved public MethodDef ResolveMethodThrow() { var method = ResolveMethod(); if (method != null) return method; throw new MemberRefResolveException(string.Format("Could not resolve method: {0} ({1})", this, this.GetDefinitionAssembly())); } bool IContainsGenericParameter.ContainsGenericParameter { get { return TypeHelper.ContainsGenericParameter(this); } } /// /// Gets a that can be used as signature context /// /// Context passed to the constructor /// Field/method class owner /// protected static GenericParamContext GetSignatureGenericParamContext(GenericParamContext gpContext, IMemberRefParent @class) { TypeDef type = null; MethodDef method = gpContext.Method; var ts = @class as TypeSpec; if (ts != null) { var gis = ts.TypeSig as GenericInstSig; if (gis != null) type = gis.GenericType.ToTypeDefOrRef().ResolveTypeDef(); } return new GenericParamContext(type, method); } /// public override string ToString() { return FullName; } } /// /// A MemberRef row created by the user and not present in the original .NET file /// public class MemberRefUser : MemberRef { /// /// Constructor /// /// Owner module public MemberRefUser(ModuleDef module) { this.module = module; } /// /// Constructor /// /// Owner module /// Name of ref public MemberRefUser(ModuleDef module, UTF8String name) { this.module = module; this.name = name; } /// /// Constructor /// /// Owner module /// Name of field ref /// Field sig public MemberRefUser(ModuleDef module, UTF8String name, FieldSig sig) : this(module, name, sig, null) { } /// /// Constructor /// /// Owner module /// Name of field ref /// Field sig /// Owner of field public MemberRefUser(ModuleDef module, UTF8String name, FieldSig sig, IMemberRefParent @class) { this.module = module; this.name = name; this.@class = @class; this.signature = sig; } /// /// Constructor /// /// Owner module /// Name of method ref /// Method sig public MemberRefUser(ModuleDef module, UTF8String name, MethodSig sig) : this(module, name, sig, null) { } /// /// Constructor /// /// Owner module /// Name of method ref /// Method sig /// Owner of method public MemberRefUser(ModuleDef module, UTF8String name, MethodSig sig, IMemberRefParent @class) { this.module = module; this.name = name; this.@class = @class; this.signature = sig; } } /// /// Created from a row in the MemberRef table /// sealed class MemberRefMD : MemberRef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; readonly GenericParamContext gpContext; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.MemberRef, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), gpContext, list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this MemberRef row /// Row ID /// Generic parameter context /// If is null /// If is invalid public MemberRefMD(ModuleDefMD readerModule, uint rid, GenericParamContext gpContext) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.MemberRefTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("MemberRef rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; this.gpContext = gpContext; this.module = readerModule; uint @class, name; uint signature = readerModule.TablesStream.ReadMemberRefRow(origRid, out @class, out name); this.name = readerModule.StringsStream.ReadNoNull(name); this.@class = readerModule.ResolveMemberRefParent(@class, gpContext); this.signature = readerModule.ReadSignature(signature, GetSignatureGenericParamContext(gpContext, this.@class)); } } } dnlib-2.1_VS2010/src/DotNet/MethodAttributes.cs000066400000000000000000000047661325033663500212040ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// Method attributes, see CorHdr.h/CorMethodAttr /// [Flags] public enum MethodAttributes : ushort { /// member access mask - Use this mask to retrieve accessibility information. MemberAccessMask = 0x0007, /// Member not referenceable. PrivateScope = 0x0000, /// Member not referenceable. CompilerControlled = PrivateScope, /// Accessible only by the parent type. Private = 0x0001, /// Accessible by sub-types only in this Assembly. FamANDAssem = 0x0002, /// Accessibly by anyone in the Assembly. Assembly = 0x0003, /// Accessible only by type and sub-types. Family = 0x0004, /// Accessibly by sub-types anywhere, plus anyone in assembly. FamORAssem = 0x0005, /// Accessibly by anyone who has visibility to this scope. Public = 0x0006, /// Defined on type, else per instance. Static = 0x0010, /// Method may not be overridden. Final = 0x0020, /// Method virtual. Virtual = 0x0040, /// Method hides by name+sig, else just by name. HideBySig = 0x0080, /// vtable layout mask - Use this mask to retrieve vtable attributes. VtableLayoutMask = 0x0100, /// The default. ReuseSlot = 0x0000, /// Method always gets a new slot in the vtable. NewSlot = 0x0100, /// Overridability is the same as the visibility. CheckAccessOnOverride = 0x0200, /// Method does not provide an implementation. Abstract = 0x0400, /// Method is special. Name describes how. SpecialName = 0x0800, /// Implementation is forwarded through pinvoke. PinvokeImpl = 0x2000, /// Implementation is forwarded through pinvoke. PInvokeImpl = PinvokeImpl, /// Managed method exported via thunk to unmanaged code. UnmanagedExport = 0x0008, /// Runtime should check name encoding. RTSpecialName = 0x1000, /// Method has security associate with it. HasSecurity = 0x4000, /// Method calls another method containing security code. RequireSecObject = 0x8000, } } dnlib-2.1_VS2010/src/DotNet/MethodDef.cs000066400000000000000000001217501325033663500175450ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Threading; using dnlib.Utils; using dnlib.PE; using dnlib.DotNet.MD; using dnlib.DotNet.Emit; using dnlib.Threading; using dnlib.DotNet.Pdb; using System.Diagnostics; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the Method table /// public abstract class MethodDef : IHasCustomAttribute, IHasDeclSecurity, IMemberRefParent, IMethodDefOrRef, IMemberForwarded, ICustomAttributeType, ITypeOrMethodDef, IManagedEntryPoint, IHasCustomDebugInformation, IListListener, IListListener, IMemberDef { internal static readonly UTF8String StaticConstructorName = ".cctor"; internal static readonly UTF8String InstanceConstructorName = ".ctor"; /// /// The row id in its table /// protected uint rid; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// /// All parameters /// protected ParameterList parameterList; /// public MDToken MDToken { get { return new MDToken(Table.Method, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 0; } } /// public int HasDeclSecurityTag { get { return 1; } } /// public int MemberRefParentTag { get { return 3; } } /// public int MethodDefOrRefTag { get { return 0; } } /// public int MemberForwardedTag { get { return 1; } } /// public int CustomAttributeTypeTag { get { return 2; } } /// public int TypeOrMethodDefTag { get { return 1; } } /// /// From column Method.RVA /// public RVA RVA { get { return rva; } set { rva = value; } } /// protected RVA rva; /// /// From column Method.ImplFlags /// public MethodImplAttributes ImplAttributes { get { return (MethodImplAttributes)implAttributes; } set { implAttributes = (int)value; } } /// Implementation attributes protected int implAttributes; /// /// From column Method.Flags /// public MethodAttributes Attributes { get { return (MethodAttributes)attributes; } set { attributes = (int)value; } } /// Attributes protected int attributes; /// /// From column Method.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// From column Method.Signature /// public CallingConventionSig Signature { get { return signature; } set { signature = value; } } /// protected CallingConventionSig signature; /// /// From column Method.ParamList /// public ThreadSafe.IList ParamDefs { get { if (paramDefs == null) InitializeParamDefs(); return paramDefs; } } /// protected LazyList paramDefs; /// Initializes protected virtual void InitializeParamDefs() { Interlocked.CompareExchange(ref paramDefs, new LazyList(this), null); } /// public ThreadSafe.IList GenericParameters { get { if (genericParameters == null) InitializeGenericParameters(); return genericParameters; } } /// protected LazyList genericParameters; /// Initializes protected virtual void InitializeGenericParameters() { Interlocked.CompareExchange(ref genericParameters, new LazyList(this), null); } /// public ThreadSafe.IList DeclSecurities { get { if (declSecurities == null) InitializeDeclSecurities(); return declSecurities; } } /// protected ThreadSafe.IList declSecurities; /// Initializes protected virtual void InitializeDeclSecurities() { Interlocked.CompareExchange(ref declSecurities, ThreadSafeListCreator.Create(), null); } /// public ImplMap ImplMap { get { if (!implMap_isInitialized) InitializeImplMap(); return implMap; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif implMap = value; implMap_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected ImplMap implMap; /// protected bool implMap_isInitialized; void InitializeImplMap() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (implMap_isInitialized) return; implMap = GetImplMap_NoLock(); implMap_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual ImplMap GetImplMap_NoLock() { return null; } /// Reset protected void ResetImplMap() { implMap_isInitialized = false; } /// /// Gets/sets the method body. See also /// public MethodBody MethodBody { get { if (!methodBody_isInitialized) InitializeMethodBody(); return methodBody; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif methodBody = value; methodBody_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected MethodBody methodBody; /// protected bool methodBody_isInitialized; void InitializeMethodBody() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (methodBody_isInitialized) return; methodBody = GetMethodBody_NoLock(); methodBody_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Frees the method body if it has been loaded. This does nothing if /// returns false. /// public void FreeMethodBody() { if (!CanFreeMethodBody) return; if (!methodBody_isInitialized) return; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif methodBody = null; methodBody_isInitialized = false; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual MethodBody GetMethodBody_NoLock() { return null; } /// /// true if can free the method body /// protected virtual bool CanFreeMethodBody { get { return true; } } /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public int HasCustomDebugInformationTag { get { return 0; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// /// Gets the methods this method implements /// public ThreadSafe.IList Overrides { get { if (overrides == null) InitializeOverrides(); return overrides; } } /// protected ThreadSafe.IList overrides; /// Initializes protected virtual void InitializeOverrides() { Interlocked.CompareExchange(ref overrides, ThreadSafeListCreator.Create(), null); } /// /// Gets the export info or null if the method isn't exported to unmanaged code. /// public MethodExportInfo ExportInfo { get { return exportInfo; } set { exportInfo = value; } } /// protected MethodExportInfo exportInfo; /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public bool HasDeclSecurities { get { return DeclSecurities.Count > 0; } } /// /// true if is not empty /// public bool HasParamDefs { get { return ParamDefs.Count > 0; } } /// /// Gets/sets the declaring type (owner type) /// public TypeDef DeclaringType { get { return declaringType2; } set { var currentDeclaringType = DeclaringType2; if (currentDeclaringType == value) return; if (currentDeclaringType != null) currentDeclaringType.Methods.Remove(this); // Will set DeclaringType2 = null if (value != null) value.Methods.Add(this); // Will set DeclaringType2 = value } } /// ITypeDefOrRef IMemberRef.DeclaringType { get { return declaringType2; } } /// /// Called by and should normally not be called by any user /// code. Use instead. Only call this if you must set the /// declaring type without inserting it in the declaring type's method list. /// public TypeDef DeclaringType2 { get { return declaringType2; } set { declaringType2 = value; } } /// protected TypeDef declaringType2; /// public ModuleDef Module { get { var dt = declaringType2; return dt == null ? null : dt.Module; } } bool IIsTypeOrMethod.IsType { get { return false; } } bool IIsTypeOrMethod.IsMethod { get { return true; } } bool IMemberRef.IsField { get { return false; } } bool IMemberRef.IsTypeSpec { get { return false; } } bool IMemberRef.IsTypeRef { get { return false; } } bool IMemberRef.IsTypeDef { get { return false; } } bool IMemberRef.IsMethodSpec { get { return false; } } bool IMemberRef.IsMethodDef { get { return true; } } bool IMemberRef.IsMemberRef { get { return false; } } bool IMemberRef.IsFieldDef { get { return false; } } bool IMemberRef.IsPropertyDef { get { return false; } } bool IMemberRef.IsEventDef { get { return false; } } bool IMemberRef.IsGenericParam { get { return false; } } /// /// Gets/sets the CIL method body. See also /// public CilBody Body { get { if (!methodBody_isInitialized) InitializeMethodBody(); return methodBody as CilBody; } set { MethodBody = value; } } /// /// Gets/sets the native method body /// public NativeMethodBody NativeBody { get { if (!methodBody_isInitialized) InitializeMethodBody(); return methodBody as NativeMethodBody; } set { MethodBody = value; } } /// /// true if there's at least one in /// public bool HasGenericParameters { get { return GenericParameters.Count > 0; } } /// /// true if it has a /// public bool HasBody { get { return Body != null; } } /// /// true if there's at least one in /// public bool HasOverrides { get { return Overrides.Count > 0; } } /// /// true if is not null /// public bool HasImplMap { get { return ImplMap != null; } } /// /// Gets the full name /// public string FullName { get { var dt = declaringType2; return FullNameCreator.MethodFullName(dt == null ? null : dt.FullName, name, MethodSig, null, null, this, null); } } /// /// Gets/sets the /// public MethodSig MethodSig { get { return signature as MethodSig; } set { signature = value; } } /// /// Gets the parameters /// public ParameterList Parameters { get { return parameterList; } } /// int IGenericParameterProvider.NumberOfGenericParameters { get { var sig = MethodSig; return sig == null ? 0 : (int)sig.GenParamCount; } } /// /// true if the method has a hidden 'this' parameter /// public bool HasThis { get { var ms = MethodSig; return ms == null ? false : ms.HasThis; } } /// /// true if the method has an explicit 'this' parameter /// public bool ExplicitThis { get { var ms = MethodSig; return ms == null ? false : ms.ExplicitThis; } } /// /// Gets the calling convention /// public CallingConvention CallingConvention { get { var ms = MethodSig; return ms == null ? 0 : ms.CallingConvention & CallingConvention.Mask; } } /// /// Gets/sets the method return type /// public TypeSig ReturnType { get { var ms = MethodSig; return ms == null ? null : ms.RetType; } set { var ms = MethodSig; if (ms != null) ms.RetType = value; } } /// /// true if the method returns a value (i.e., return type is not ) /// public bool HasReturnType { get { return ReturnType.RemovePinnedAndModifiers().GetElementType() != ElementType.Void; } } /// /// Gets/sets the method semantics attributes. If you remove/add a method to a property or /// an event, you must manually update this property or eg. won't /// work as expected. /// public MethodSemanticsAttributes SemanticsAttributes { get { if ((semAttrs & SEMATTRS_INITD) == 0) InitializeSemanticsAttributes(); return (MethodSemanticsAttributes)semAttrs; } set { semAttrs = (ushort)value | SEMATTRS_INITD; } } /// Set when has been initialized protected internal static int SEMATTRS_INITD = unchecked((int)0x80000000); /// protected internal int semAttrs; /// Initializes protected virtual void InitializeSemanticsAttributes() { semAttrs = 0 | SEMATTRS_INITD; } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyAttributes(bool set, MethodSemanticsAttributes flags) { if ((semAttrs & SEMATTRS_INITD) == 0) InitializeSemanticsAttributes(); #if THREAD_SAFE int origVal, newVal; do { origVal = semAttrs; if (set) newVal = origVal | (int)flags; else newVal = origVal & ~(int)flags; } while (Interlocked.CompareExchange(ref semAttrs, newVal, origVal) != origVal); #else if (set) semAttrs |= (int)flags; else semAttrs &= ~(int)flags; #endif } /// /// Modify property: = /// ( & ) | . /// /// Value to AND /// Value to OR void ModifyAttributes(MethodAttributes andMask, MethodAttributes 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 attributes = (attributes & (int)andMask) | (int)orMask; #endif } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyAttributes(bool set, MethodAttributes 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 } /// /// Modify property: = /// ( & ) | . /// /// Value to AND /// Value to OR void ModifyImplAttributes(MethodImplAttributes andMask, MethodImplAttributes orMask) { #if THREAD_SAFE int origVal, newVal; do { origVal = implAttributes; newVal = (origVal & (int)andMask) | (int)orMask; } while (Interlocked.CompareExchange(ref implAttributes, newVal, origVal) != origVal); #else implAttributes = (implAttributes & (int)andMask) | (int)orMask; #endif } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyImplAttributes(bool set, MethodImplAttributes flags) { #if THREAD_SAFE int origVal, newVal; do { origVal = implAttributes; if (set) newVal = origVal | (int)flags; else newVal = origVal & ~(int)flags; } while (Interlocked.CompareExchange(ref implAttributes, newVal, origVal) != origVal); #else if (set) implAttributes |= (int)flags; else implAttributes &= ~(int)flags; #endif } /// /// Gets/sets the method access /// public MethodAttributes Access { get { return (MethodAttributes)attributes & MethodAttributes.MemberAccessMask; } set { ModifyAttributes(~MethodAttributes.MemberAccessMask, value & MethodAttributes.MemberAccessMask); } } /// /// true if is set /// public bool IsCompilerControlled { get { return IsPrivateScope; } } /// /// true if is set /// public bool IsPrivateScope { get { return ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope; } } /// /// true if is set /// public bool IsPrivate { get { return ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private; } } /// /// true if is set /// public bool IsFamilyAndAssembly { get { return ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem; } } /// /// true if is set /// public bool IsAssembly { get { return ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly; } } /// /// true if is set /// public bool IsFamily { get { return ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family; } } /// /// true if is set /// public bool IsFamilyOrAssembly { get { return ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem; } } /// /// true if is set /// public bool IsPublic { get { return ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public; } } /// /// Gets/sets the bit /// public bool IsStatic { get { return ((MethodAttributes)attributes & MethodAttributes.Static) != 0; } set { ModifyAttributes(value, MethodAttributes.Static); } } /// /// Gets/sets the bit /// public bool IsFinal { get { return ((MethodAttributes)attributes & MethodAttributes.Final) != 0; } set { ModifyAttributes(value, MethodAttributes.Final); } } /// /// Gets/sets the bit /// public bool IsVirtual { get { return ((MethodAttributes)attributes & MethodAttributes.Virtual) != 0; } set { ModifyAttributes(value, MethodAttributes.Virtual); } } /// /// Gets/sets the bit /// public bool IsHideBySig { get { return ((MethodAttributes)attributes & MethodAttributes.HideBySig) != 0; } set { ModifyAttributes(value, MethodAttributes.HideBySig); } } /// /// Gets/sets the bit /// public bool IsNewSlot { get { return ((MethodAttributes)attributes & MethodAttributes.NewSlot) != 0; } set { ModifyAttributes(value, MethodAttributes.NewSlot); } } /// /// Gets/sets the bit /// public bool IsReuseSlot { get { return ((MethodAttributes)attributes & MethodAttributes.NewSlot) == 0; } set { ModifyAttributes(!value, MethodAttributes.NewSlot); } } /// /// Gets/sets the bit /// public bool IsCheckAccessOnOverride { get { return ((MethodAttributes)attributes & MethodAttributes.CheckAccessOnOverride) != 0; } set { ModifyAttributes(value, MethodAttributes.CheckAccessOnOverride); } } /// /// Gets/sets the bit /// public bool IsAbstract { get { return ((MethodAttributes)attributes & MethodAttributes.Abstract) != 0; } set { ModifyAttributes(value, MethodAttributes.Abstract); } } /// /// Gets/sets the bit /// public bool IsSpecialName { get { return ((MethodAttributes)attributes & MethodAttributes.SpecialName) != 0; } set { ModifyAttributes(value, MethodAttributes.SpecialName); } } /// /// Gets/sets the bit /// public bool IsPinvokeImpl { get { return ((MethodAttributes)attributes & MethodAttributes.PinvokeImpl) != 0; } set { ModifyAttributes(value, MethodAttributes.PinvokeImpl); } } /// /// Gets/sets the bit /// public bool IsUnmanagedExport { get { return ((MethodAttributes)attributes & MethodAttributes.UnmanagedExport) != 0; } set { ModifyAttributes(value, MethodAttributes.UnmanagedExport); } } /// /// Gets/sets the bit /// public bool IsRuntimeSpecialName { get { return ((MethodAttributes)attributes & MethodAttributes.RTSpecialName) != 0; } set { ModifyAttributes(value, MethodAttributes.RTSpecialName); } } /// /// Gets/sets the bit /// public bool HasSecurity { get { return ((MethodAttributes)attributes & MethodAttributes.HasSecurity) != 0; } set { ModifyAttributes(value, MethodAttributes.HasSecurity); } } /// /// Gets/sets the bit /// public bool IsRequireSecObject { get { return ((MethodAttributes)attributes & MethodAttributes.RequireSecObject) != 0; } set { ModifyAttributes(value, MethodAttributes.RequireSecObject); } } /// /// Gets/sets the code type /// public MethodImplAttributes CodeType { get { return (MethodImplAttributes)implAttributes & MethodImplAttributes.CodeTypeMask; } set { ModifyImplAttributes(~MethodImplAttributes.CodeTypeMask, value & MethodImplAttributes.CodeTypeMask); } } /// /// true if is set /// public bool IsIL { get { return ((MethodImplAttributes)implAttributes & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.IL; } } /// /// true if is set /// public bool IsNative { get { return ((MethodImplAttributes)implAttributes & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.Native; } } /// /// true if is set /// public bool IsOPTIL { get { return ((MethodImplAttributes)implAttributes & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.OPTIL; } } /// /// true if is set /// public bool IsRuntime { get { return ((MethodImplAttributes)implAttributes & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.Runtime; } } /// /// Gets/sets the bit /// public bool IsUnmanaged { get { return ((MethodImplAttributes)implAttributes & MethodImplAttributes.Unmanaged) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.Unmanaged); } } /// /// Gets/sets the bit /// public bool IsManaged { get { return ((MethodImplAttributes)implAttributes & MethodImplAttributes.Unmanaged) == 0; } set { ModifyImplAttributes(!value, MethodImplAttributes.Unmanaged); } } /// /// Gets/sets the bit /// public bool IsForwardRef { get { return ((MethodImplAttributes)implAttributes & MethodImplAttributes.ForwardRef) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.ForwardRef); } } /// /// Gets/sets the bit /// public bool IsPreserveSig { get { return ((MethodImplAttributes)implAttributes & MethodImplAttributes.PreserveSig) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.PreserveSig); } } /// /// Gets/sets the bit /// public bool IsInternalCall { get { return ((MethodImplAttributes)implAttributes & MethodImplAttributes.InternalCall) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.InternalCall); } } /// /// Gets/sets the bit /// public bool IsSynchronized { get { return ((MethodImplAttributes)implAttributes & MethodImplAttributes.Synchronized) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.Synchronized); } } /// /// Gets/sets the bit /// public bool IsNoInlining { get { return ((MethodImplAttributes)implAttributes & MethodImplAttributes.NoInlining) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.NoInlining); } } /// /// Gets/sets the bit /// public bool IsAggressiveInlining { get { return ((MethodImplAttributes)implAttributes & MethodImplAttributes.AggressiveInlining) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.AggressiveInlining); } } /// /// Gets/sets the bit /// public bool IsNoOptimization { get { return ((MethodImplAttributes)implAttributes & MethodImplAttributes.NoOptimization) != 0; } set { ModifyImplAttributes(value, MethodImplAttributes.NoOptimization); } } /// /// Gets/sets the bit /// public bool IsSetter { get { return (SemanticsAttributes & MethodSemanticsAttributes.Setter) != 0; } set { ModifyAttributes(value, MethodSemanticsAttributes.Setter); } } /// /// Gets/sets the bit /// public bool IsGetter { get { return (SemanticsAttributes & MethodSemanticsAttributes.Getter) != 0; } set { ModifyAttributes(value, MethodSemanticsAttributes.Getter); } } /// /// Gets/sets the bit /// public bool IsOther { get { return (SemanticsAttributes & MethodSemanticsAttributes.Other) != 0; } set { ModifyAttributes(value, MethodSemanticsAttributes.Other); } } /// /// Gets/sets the bit /// public bool IsAddOn { get { return (SemanticsAttributes & MethodSemanticsAttributes.AddOn) != 0; } set { ModifyAttributes(value, MethodSemanticsAttributes.AddOn); } } /// /// Gets/sets the bit /// public bool IsRemoveOn { get { return (SemanticsAttributes & MethodSemanticsAttributes.RemoveOn) != 0; } set { ModifyAttributes(value, MethodSemanticsAttributes.RemoveOn); } } /// /// Gets/sets the bit /// public bool IsFire { get { return (SemanticsAttributes & MethodSemanticsAttributes.Fire) != 0; } set { ModifyAttributes(value, MethodSemanticsAttributes.Fire); } } /// /// true if this is the static type constructor /// public bool IsStaticConstructor { get { return IsRuntimeSpecialName && UTF8String.Equals(name, StaticConstructorName); } } /// /// true if this is an instance constructor /// public bool IsInstanceConstructor { get { return IsRuntimeSpecialName && UTF8String.Equals(name, InstanceConstructorName); } } /// /// true if this is a static or an instance constructor /// public bool IsConstructor { get { return IsStaticConstructor || IsInstanceConstructor; } } /// void IListListener.OnLazyAdd(int index, ref GenericParam value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref GenericParam value) { #if DEBUG if (value.Owner != this) throw new InvalidOperationException("Added generic param's Owner != this"); #endif } /// void IListListener.OnAdd(int index, GenericParam value) { if (value.Owner != null) throw new InvalidOperationException("Generic param is already owned by another type/method. Set Owner to null first."); value.Owner = this; } /// void IListListener.OnRemove(int index, GenericParam value) { value.Owner = null; } /// void IListListener.OnResize(int index) { } /// void IListListener.OnClear() { foreach (var gp in GenericParameters.GetEnumerable_NoLock()) gp.Owner = null; } /// void IListListener.OnLazyAdd(int index, ref ParamDef value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref ParamDef value) { #if DEBUG if (value.DeclaringMethod != this) throw new InvalidOperationException("Added param's DeclaringMethod != this"); #endif } /// void IListListener.OnAdd(int index, ParamDef value) { if (value.DeclaringMethod != null) throw new InvalidOperationException("Param is already owned by another method. Set DeclaringMethod to null first."); value.DeclaringMethod = this; } /// void IListListener.OnRemove(int index, ParamDef value) { value.DeclaringMethod = null; } /// void IListListener.OnResize(int index) { } /// void IListListener.OnClear() { foreach (var pd in ParamDefs.GetEnumerable_NoLock()) pd.DeclaringMethod = null; } /// public override string ToString() { return FullName; } } /// /// A Method row created by the user and not present in the original .NET file /// public class MethodDefUser : MethodDef { /// /// Default constructor /// public MethodDefUser() { this.paramDefs = new LazyList(this); this.genericParameters = new LazyList(this); this.parameterList = new ParameterList(this, null); this.semAttrs = 0 | SEMATTRS_INITD; } /// /// Constructor /// /// Method name public MethodDefUser(UTF8String name) : this(name, null, 0, 0) { } /// /// Constructor /// /// Method name /// Method sig public MethodDefUser(UTF8String name, MethodSig methodSig) : this(name, methodSig, 0, 0) { } /// /// Constructor /// /// Method name /// Method sig /// Flags public MethodDefUser(UTF8String name, MethodSig methodSig, MethodAttributes flags) : this(name, methodSig, 0, flags) { } /// /// Constructor /// /// Method name /// Method sig /// Impl flags public MethodDefUser(UTF8String name, MethodSig methodSig, MethodImplAttributes implFlags) : this(name, methodSig, implFlags, 0) { } /// /// Constructor /// /// Method name /// Method sig /// Impl flags /// Flags public MethodDefUser(UTF8String name, MethodSig methodSig, MethodImplAttributes implFlags, MethodAttributes flags) { this.name = name; this.signature = methodSig; this.paramDefs = new LazyList(this); this.genericParameters = new LazyList(this); this.implAttributes = (int)implFlags; this.attributes = (int)flags; this.parameterList = new ParameterList(this, null); this.semAttrs = 0 | SEMATTRS_INITD; } } /// /// Created from a row in the Method table /// sealed class MethodDefMD : MethodDef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; readonly RVA origRva; readonly MethodImplAttributes origImplAttributes; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeParamDefs() { var list = readerModule.MetaData.GetParamRidList(origRid); var tmp = new LazyList((int)list.Length, this, list, (list2, index) => readerModule.ResolveParam(((RidList)list2)[index])); Interlocked.CompareExchange(ref paramDefs, tmp, null); } /// protected override void InitializeGenericParameters() { var list = readerModule.MetaData.GetGenericParamRidList(Table.Method, origRid); var tmp = new LazyList((int)list.Length, this, list, (list2, index) => readerModule.ResolveGenericParam(((RidList)list2)[index])); Interlocked.CompareExchange(ref genericParameters, tmp, null); } /// protected override void InitializeDeclSecurities() { var list = readerModule.MetaData.GetDeclSecurityRidList(Table.Method, origRid); var tmp = new LazyList((int)list.Length, list, (list2, index) => readerModule.ResolveDeclSecurity(((RidList)list2)[index])); Interlocked.CompareExchange(ref declSecurities, tmp, null); } /// protected override ImplMap GetImplMap_NoLock() { return readerModule.ResolveImplMap(readerModule.MetaData.GetImplMapRid(Table.Method, origRid)); } /// protected override MethodBody GetMethodBody_NoLock() { return readerModule.ReadMethodBody(this, origRva, origImplAttributes, new GenericParamContext(declaringType2, this)); } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.Method, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); if (Interlocked.CompareExchange(ref customDebugInfos, list, null) == null) { var body = Body; readerModule.InitializeCustomDebugInfos(this, body, list); } } /// protected override void InitializeOverrides() { var dt = declaringType2 as TypeDefMD; var tmp = dt == null ? ThreadSafeListCreator.Create() : dt.GetMethodOverrides(this, new GenericParamContext(declaringType2, this)); Interlocked.CompareExchange(ref overrides, tmp, null); } /// protected override void InitializeSemanticsAttributes() { var dt = DeclaringType as TypeDefMD; if (dt != null) dt.InitializeMethodSemanticsAttributes(); semAttrs |= SEMATTRS_INITD; } /// /// Constructor /// /// The module which contains this Method row /// Row ID /// If is null /// If is invalid public MethodDefMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.MethodTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("Method rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; uint name; uint signature = readerModule.TablesStream.ReadMethodRow(origRid, out this.rva, out this.implAttributes, out this.attributes, out name); this.name = readerModule.StringsStream.ReadNoNull(name); this.origRva = rva; this.origImplAttributes = (MethodImplAttributes)implAttributes; this.declaringType2 = readerModule.GetOwnerType(this); this.signature = readerModule.ReadSignature(signature, new GenericParamContext(declaringType2, this)); this.parameterList = new ParameterList(this, declaringType2); this.exportInfo = readerModule.GetExportInfo(rid); } internal MethodDefMD InitializeAll() { MemberMDInitializer.Initialize(RVA); MemberMDInitializer.Initialize(Attributes); MemberMDInitializer.Initialize(ImplAttributes); MemberMDInitializer.Initialize(Name); MemberMDInitializer.Initialize(Signature); MemberMDInitializer.Initialize(ImplMap); MemberMDInitializer.Initialize(MethodBody); MemberMDInitializer.Initialize(DeclaringType); MemberMDInitializer.Initialize(CustomAttributes); MemberMDInitializer.Initialize(Overrides); MemberMDInitializer.Initialize(ParamDefs); MemberMDInitializer.Initialize(GenericParameters); MemberMDInitializer.Initialize(DeclSecurities); return this; } /// internal override void OnLazyAdd2(int index, ref GenericParam value) { if (value.Owner != this) { // More than one owner... This module has invalid metadata. value = readerModule.ForceUpdateRowId(readerModule.ReadGenericParam(value.Rid).InitializeAll()); value.Owner = this; } } /// internal override void OnLazyAdd2(int index, ref ParamDef value) { if (value.DeclaringMethod != this) { // More than one owner... This module has invalid metadata. value = readerModule.ForceUpdateRowId(readerModule.ReadParam(value.Rid).InitializeAll()); value.DeclaringMethod = this; } } } } dnlib-2.1_VS2010/src/DotNet/MethodExportInfo.cs000066400000000000000000000053551325033663500211460ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Diagnostics; namespace dnlib.DotNet { /// /// Contains the name and ordinal of a method that gets exported to unmanaged code. /// [DebuggerDisplay("{Ordinal} {Name} {Options}")] public sealed class MethodExportInfo { MethodExportInfoOptions options; ushort? ordinal; string name; const MethodExportInfoOptions DefaultOptions = MethodExportInfoOptions.FromUnmanaged; /// /// Gets the ordinal or null /// public ushort? Ordinal { get { return ordinal; } set { ordinal = value; } } /// /// Gets the name. If it's null, and is also null, the name of the method /// () is used as the exported name. /// public string Name { get { return name; } set { name = value; } } /// /// Gets the options /// public MethodExportInfoOptions Options { get { return options; } set { options = value; } } /// /// Constructor /// public MethodExportInfo() { options = DefaultOptions; } /// /// Constructor /// /// Name or null to export by ordinal public MethodExportInfo(string name) { options = DefaultOptions; this.name = name; } /// /// Constructor /// /// Ordinal public MethodExportInfo(ushort ordinal) { options = DefaultOptions; this.ordinal = ordinal; } /// /// Constructor /// /// Name or null to export by ordinal /// Ordinal or null to export by name public MethodExportInfo(string name, ushort? ordinal) { options = DefaultOptions; this.name = name; this.ordinal = ordinal; } /// /// Constructor /// /// Name or null to export by ordinal /// Ordinal or null to export by name /// Options public MethodExportInfo(string name, ushort? ordinal, MethodExportInfoOptions options) { this.options = options; this.name = name; this.ordinal = ordinal; } } /// /// Exported method options /// public enum MethodExportInfoOptions { /// /// No bit is set /// None = 0, /// /// Transition from unmanaged code /// FromUnmanaged = 0x00000001, /// /// Also retain app domain /// FromUnmanagedRetainAppDomain = 0x00000002, /// /// Call most derived method /// CallMostDerived = 0x00000004, } } dnlib-2.1_VS2010/src/DotNet/MethodExportInfoProvider.cs000066400000000000000000000134251325033663500226560ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.PE; using dnlib.IO; using System.Diagnostics; using System.Text; namespace dnlib.DotNet { sealed class MethodExportInfoProvider { readonly Dictionary toInfo; public MethodExportInfoProvider(ModuleDefMD module) { toInfo = new Dictionary(); try { Initialize(module); } catch (OutOfMemoryException) { } catch (IOException) { } } void Initialize(ModuleDefMD module) { var vtblHdr = module.MetaData.ImageCor20Header.VTableFixups; if (vtblHdr.VirtualAddress == 0 || vtblHdr.Size == 0) return; var peImage = module.MetaData.PEImage; var exportHdr = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[0]; if (exportHdr.VirtualAddress == 0 || exportHdr.Size < 0x28) return; CpuArch cpuArch; if (!CpuArch.TryGetCpuArch(peImage.ImageNTHeaders.FileHeader.Machine, out cpuArch)) { Debug.Fail(string.Format("Exported methods: Unsupported machine: {0}", peImage.ImageNTHeaders.FileHeader.Machine)); return; } using (var reader = peImage.CreateFullStream()) { var offsetToInfo = GetOffsetToExportInfoDictionary(reader, peImage, exportHdr, cpuArch); reader.Position = (long)peImage.ToFileOffset(vtblHdr.VirtualAddress); long endPos = reader.Position + vtblHdr.Size; while (reader.Position + 8 <= endPos && reader.CanRead(8)) { var tableRva = (RVA)reader.ReadUInt32(); int numSlots = reader.ReadUInt16(); var flags = (VTableFlags)reader.ReadUInt16(); bool is64bit = (flags & VTableFlags._64Bit) != 0; var exportOptions = ToMethodExportInfoOptions(flags); var pos = reader.Position; reader.Position = (long)peImage.ToFileOffset(tableRva); int slotSize = is64bit ? 8 : 4; while (numSlots-- > 0 && reader.CanRead(slotSize)) { var tokenPos = reader.Position; MethodExportInfo exportInfo; uint token = reader.ReadUInt32(); bool b = offsetToInfo.TryGetValue(tokenPos, out exportInfo); Debug.Assert(token == 0 || b); if (b) { exportInfo = new MethodExportInfo(exportInfo.Name, exportInfo.Ordinal, exportOptions); toInfo[token] = exportInfo; } if (slotSize == 8) reader.ReadUInt32(); } reader.Position = pos; } } } static MethodExportInfoOptions ToMethodExportInfoOptions(VTableFlags flags) { var res = MethodExportInfoOptions.None; if ((flags & VTableFlags.FromUnmanaged) != 0) res |= MethodExportInfoOptions.FromUnmanaged; if ((flags & VTableFlags.FromUnmanagedRetainAppDomain) != 0) res |= MethodExportInfoOptions.FromUnmanagedRetainAppDomain; if ((flags & VTableFlags.CallMostDerived) != 0) res |= MethodExportInfoOptions.CallMostDerived; return res; } static Dictionary GetOffsetToExportInfoDictionary(IImageStream reader, IPEImage peImage, ImageDataDirectory exportHdr, CpuArch cpuArch) { reader.Position = (long)peImage.ToFileOffset(exportHdr.VirtualAddress); // Skip Characteristics(4), TimeDateStamp(4), MajorVersion(2), MinorVersion(2), Name(4) reader.Position += 16; uint ordinalBase = reader.ReadUInt32(); int numFuncs = reader.ReadInt32(); int numNames = reader.ReadInt32(); long offsetOfFuncs = (long)peImage.ToFileOffset((RVA)reader.ReadUInt32()); long offsetOfNames = (long)peImage.ToFileOffset((RVA)reader.ReadUInt32()); long offsetOfNameIndexes = (long)peImage.ToFileOffset((RVA)reader.ReadUInt32()); var names = ReadNames(reader, peImage, numNames, offsetOfNames, offsetOfNameIndexes); reader.Position = offsetOfFuncs; var allInfos = new MethodExportInfo[numFuncs]; var dict = new Dictionary(numFuncs); for (int i = 0; i < allInfos.Length; i++) { var currOffset = reader.Position; var nextOffset = reader.Position + 4; uint funcRva = 0; var rva = (RVA)reader.ReadUInt32(); reader.Position = (long)peImage.ToFileOffset(rva); bool rvaValid = rva != 0 && cpuArch.TryGetExportedRvaFromStub(reader, peImage, out funcRva); long funcOffset = rvaValid ? (long)peImage.ToFileOffset((RVA)funcRva) : 0; var exportInfo = new MethodExportInfo((ushort)(ordinalBase + (uint)i)); if (funcOffset != 0) dict[funcOffset] = exportInfo; allInfos[i] = exportInfo; reader.Position = nextOffset; } foreach (var info in names) { int index = info.Index; if ((uint)index >= (uint)numFuncs) continue; allInfos[index].Ordinal = null; allInfos[index].Name = info.Name; } return dict; } static NameAndIndex[] ReadNames(IImageStream reader, IPEImage peImage, int numNames, long offsetOfNames, long offsetOfNameIndexes) { var names = new NameAndIndex[numNames]; reader.Position = offsetOfNameIndexes; for (int i = 0; i < names.Length; i++) names[i].Index = reader.ReadUInt16(); var currentOffset = offsetOfNames; for (int i = 0; i < names.Length; i++, currentOffset += 4) { reader.Position = currentOffset; long offsetOfName = (long)peImage.ToFileOffset((RVA)reader.ReadUInt32()); names[i].Name = ReadMethodNameASCIIZ(reader, offsetOfName); } return names; } struct NameAndIndex { public string Name; public int Index; } // If this method gets updated, also update the writer (ManagedExportsWriter) static string ReadMethodNameASCIIZ(IImageStream reader, long offset) { reader.Position = offset; var stringData = reader.ReadBytesUntilByte(0); return Encoding.UTF8.GetString(stringData); } public MethodExportInfo GetMethodExportInfo(uint token) { if (toInfo.Count == 0) return null; MethodExportInfo info; if (toInfo.TryGetValue(token, out info)) return new MethodExportInfo(info.Name, info.Ordinal, info.Options); return null; } } } dnlib-2.1_VS2010/src/DotNet/MethodImplAttributes.cs000066400000000000000000000027701325033663500220170ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// Method impl attributes, see CorHdr.h/CorMethodImpl /// [Flags] public enum MethodImplAttributes : ushort { /// Flags about code type. CodeTypeMask = 0x0003, /// Method impl is IL. IL = 0x0000, /// Method impl is native. Native = 0x0001, /// Method impl is OPTIL OPTIL = 0x0002, /// Method impl is provided by the runtime. Runtime = 0x0003, /// Flags specifying whether the code is managed or unmanaged. ManagedMask = 0x0004, /// Method impl is unmanaged, otherwise managed. Unmanaged = 0x0004, /// Method impl is managed. Managed = 0x0000, /// Indicates method is defined; used primarily in merge scenarios. ForwardRef = 0x0010, /// Indicates method sig is not to be mangled to do HRESULT conversion. PreserveSig = 0x0080, /// Reserved for internal use. InternalCall = 0x1000, /// Method is single threaded through the body. Synchronized = 0x0020, /// Method may not be inlined. NoInlining = 0x0008, /// Method should be inlined if possible. AggressiveInlining = 0x0100, /// Method may not be optimized. NoOptimization = 0x0040, } } dnlib-2.1_VS2010/src/DotNet/MethodOverride.cs000066400000000000000000000015331325033663500206220ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Describes which method some method implements /// public struct MethodOverride { /// /// The method body. Usually a but could be a /// public IMethodDefOrRef MethodBody; /// /// The method implements /// public IMethodDefOrRef MethodDeclaration; /// /// Constructor /// /// Method body /// The method implements public MethodOverride(IMethodDefOrRef methodBody, IMethodDefOrRef methodDeclaration) { this.MethodBody = methodBody; this.MethodDeclaration = methodDeclaration; } } } dnlib-2.1_VS2010/src/DotNet/MethodSemanticsAttributes.cs000066400000000000000000000013051325033663500230350ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// Method semantics flags, see CorHdr.h/CorMethodSemanticsAttr /// [Flags] public enum MethodSemanticsAttributes : ushort { /// No bit is set None = 0, /// Setter for property Setter = 0x0001, /// Getter for property Getter = 0x0002, /// other method for property or event Other = 0x0004, /// AddOn method for event AddOn = 0x0008, /// RemoveOn method for event RemoveOn = 0x0010, /// Fire method for event Fire = 0x0020, } } dnlib-2.1_VS2010/src/DotNet/MethodSpec.cs000066400000000000000000000213501325033663500177340ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the MethodSpec table /// public abstract class MethodSpec : IHasCustomAttribute, IHasCustomDebugInformation, IMethod, IContainsGenericParameter { /// /// The row id in its table /// protected uint rid; /// public MDToken MDToken { get { return new MDToken(Table.MethodSpec, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 21; } } /// /// From column MethodSpec.Method /// public IMethodDefOrRef Method { get { return method; } set { method = value; } } /// protected IMethodDefOrRef method; /// /// From column MethodSpec.Instantiation /// public CallingConventionSig Instantiation { get { return instantiation; } set { instantiation = value; } } /// protected CallingConventionSig instantiation; /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 21; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// MethodSig IMethod.MethodSig { get { var m = method; return m == null ? null : m.MethodSig; } set { var m = method; if (m != null) m.MethodSig = value; } } /// public UTF8String Name { get { var m = method; return m == null ? UTF8String.Empty : m.Name; } set { var m = method; if (m != null) m.Name = value; } } /// public ITypeDefOrRef DeclaringType { get { var m = method; return m == null ? null : m.DeclaringType; } } /// /// Gets/sets the generic instance method sig /// public GenericInstMethodSig GenericInstMethodSig { get { return instantiation as GenericInstMethodSig; } set { instantiation = value; } } /// int IGenericParameterProvider.NumberOfGenericParameters { get { var sig = GenericInstMethodSig; return sig == null ? 0 : sig.GenericArguments.Count; } } /// public ModuleDef Module { get { var m = method; return m == null ? null : m.Module; } } /// /// Gets the full name /// public string FullName { get { var gims = GenericInstMethodSig; var methodGenArgs = gims == null ? null : gims.GenericArguments; var m = method; var methodDef = m as MethodDef; if (methodDef != null) { var declaringType = methodDef.DeclaringType; return FullNameCreator.MethodFullName(declaringType == null ? null : declaringType.FullName, methodDef.Name, methodDef.MethodSig, null, methodGenArgs, null, null); } var memberRef = m as MemberRef; if (memberRef != null) { var methodSig = memberRef.MethodSig; if (methodSig != null) { var tsOwner = memberRef.Class as TypeSpec; var gis = tsOwner == null ? null : tsOwner.TypeSig as GenericInstSig; var typeGenArgs = gis == null ? null : gis.GenericArguments; return FullNameCreator.MethodFullName(memberRef.GetDeclaringTypeFullName(), memberRef.Name, methodSig, typeGenArgs, methodGenArgs, null, null); } } return string.Empty; } } bool IIsTypeOrMethod.IsType { get { return false; } } bool IIsTypeOrMethod.IsMethod { get { return true; } } bool IMemberRef.IsField { get { return false; } } bool IMemberRef.IsTypeSpec { get { return false; } } bool IMemberRef.IsTypeRef { get { return false; } } bool IMemberRef.IsTypeDef { get { return false; } } bool IMemberRef.IsMethodSpec { get { return true; } } bool IMemberRef.IsMethodDef { get { return false; } } bool IMemberRef.IsMemberRef { get { return false; } } bool IMemberRef.IsFieldDef { get { return false; } } bool IMemberRef.IsPropertyDef { get { return false; } } bool IMemberRef.IsEventDef { get { return false; } } bool IMemberRef.IsGenericParam { get { return false; } } bool IContainsGenericParameter.ContainsGenericParameter { get { return TypeHelper.ContainsGenericParameter(this); } } /// public override string ToString() { return FullName; } } /// /// A MethodSpec row created by the user and not present in the original .NET file /// public class MethodSpecUser : MethodSpec { /// /// Default constructor /// public MethodSpecUser() { } /// /// Constructor /// /// The generic method public MethodSpecUser(IMethodDefOrRef method) : this(method, null) { } /// /// Constructor /// /// The generic method /// The instantiated method sig public MethodSpecUser(IMethodDefOrRef method, GenericInstMethodSig sig) { this.method = method; this.instantiation = sig; } } /// /// Created from a row in the MethodSpec table /// sealed class MethodSpecMD : MethodSpec, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; readonly GenericParamContext gpContext; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.MethodSpec, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), gpContext, list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this MethodSpec row /// Row ID /// Generic parameter context /// If is null /// If is invalid public MethodSpecMD(ModuleDefMD readerModule, uint rid, GenericParamContext gpContext) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.MethodSpecTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("MethodSpec rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; this.gpContext = gpContext; uint method; uint instantiation = readerModule.TablesStream.ReadMethodSpecRow(origRid, out method); this.method = readerModule.ResolveMethodDefOrRef(method, gpContext); this.instantiation = readerModule.ReadSignature(instantiation, gpContext); } } } dnlib-2.1_VS2010/src/DotNet/ModuleContext.cs000066400000000000000000000036031325033663500204740ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Threading; namespace dnlib.DotNet { /// /// context /// public class ModuleContext { IAssemblyResolver assemblyResolver; IResolver resolver; /// /// Gets/sets the assembly resolver. This is never null. /// public IAssemblyResolver AssemblyResolver { get { if (assemblyResolver == null) Interlocked.CompareExchange(ref assemblyResolver, NullResolver.Instance, null); return assemblyResolver; } set { assemblyResolver = value; } } /// /// Gets/sets the resolver. This is never null. /// public IResolver Resolver { get { if (resolver == null) Interlocked.CompareExchange(ref resolver, NullResolver.Instance, null); return resolver; } set { resolver = value; } } /// /// Default constructor /// public ModuleContext() { } /// /// Constructor /// /// Assembly resolver or null public ModuleContext(IAssemblyResolver assemblyResolver) : this(assemblyResolver, new Resolver(assemblyResolver)) { } /// /// Constructor /// /// Type/method/field resolver or null public ModuleContext(IResolver resolver) : this(null, resolver) { } /// /// Constructor /// /// Assembly resolver or null /// Type/method/field resolver or null public ModuleContext(IAssemblyResolver assemblyResolver, IResolver resolver) { this.assemblyResolver = assemblyResolver; this.resolver = resolver; if (resolver == null && assemblyResolver != null) this.resolver = new Resolver(assemblyResolver); } } } dnlib-2.1_VS2010/src/DotNet/ModuleCreationOptions.cs000066400000000000000000000051221325033663500221660ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.IO; using dnlib.DotNet.Pdb; using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet { /// /// creation options /// public sealed class ModuleCreationOptions { internal static readonly ModuleCreationOptions Default = new ModuleCreationOptions(); /// /// Module context /// public ModuleContext Context { get; set; } /// /// Set this if you want to decide how to create the PDB symbol reader. You don't need to /// initialize or . /// public CreateSymbolReaderDelegate CreateSymbolReader { get; set; } /// /// Which PDB reader to use. Default is . /// public PdbImplType PdbImplementation { get; set; } /// /// Set it to A) the path (string) of the PDB file, B) the data (byte[]) of the PDB file or /// C) to an of the PDB data. The will /// be owned by the module. You don't need to initialize /// or /// public object PdbFileOrData { get; set; } /// /// If true, will load the PDB file from disk if present, or an embedded portable PDB file /// stored in the PE file. The default value is true. /// You don't need to initialize or . /// public bool TryToLoadPdbFromDisk { get; set; } /// /// corlib assembly reference to use or null if the default one from the opened /// module should be used. /// public AssemblyRef CorLibAssemblyRef { get; set; } /// /// Default constructor /// public ModuleCreationOptions() { this.PdbImplementation = PdbImplType.Default; this.TryToLoadPdbFromDisk = true; } /// /// Constructor /// /// Module context public ModuleCreationOptions(ModuleContext context) { this.Context = context; this.PdbImplementation = PdbImplType.Default; this.TryToLoadPdbFromDisk = true; } } /// /// Creates a /// /// Module /// A instance for (and now owned by) /// or null. public delegate SymbolReader CreateSymbolReaderDelegate(ModuleDefMD module); } dnlib-2.1_VS2010/src/DotNet/ModuleDef.cs000066400000000000000000001523601325033663500175530ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Threading; using dnlib.Utils; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.DotNet.Writer; using dnlib.PE; using dnlib.Threading; using dnlib.W32Resources; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the Module table /// public abstract class ModuleDef : IHasCustomAttribute, IHasCustomDebugInformation, IResolutionScope, IDisposable, IListListener, IModule, ITypeDefFinder, IDnlibDef, ITokenResolver, ISignatureReaderHelper { /// Default characteristics protected const Characteristics DefaultCharacteristics = Characteristics.ExecutableImage | Characteristics._32BitMachine; /// Default DLL characteristics protected const DllCharacteristics DefaultDllCharacteristics = DllCharacteristics.TerminalServerAware | DllCharacteristics.NoSeh | DllCharacteristics.NxCompat | DllCharacteristics.DynamicBase; /// /// The row id in its table /// protected uint rid; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// /// Initialize this in the ctor /// protected ICorLibTypes corLibTypes; /// /// PDB state /// protected PdbState pdbState; TypeDefFinder typeDefFinder; /// /// Array of last used rid in each table. I.e., next free rid is value + 1 /// protected readonly int[] lastUsedRids = new int[64]; /// Module context protected ModuleContext context; /// public MDToken MDToken { get { return new MDToken(Table.Module, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 7; } } /// public int ResolutionScopeTag { get { return 0; } } /// /// Gets/sets a user value. This is never used by dnlib. This property isn't thread safe. /// public object Tag { get { return tag; } set { tag = value; } } object tag; /// public ScopeType ScopeType { get { return ScopeType.ModuleDef; } } /// public string ScopeName { get { return FullName; } } /// /// Gets/sets Module.Generation column /// public ushort Generation { get { return generation; } set { generation = value; } } /// protected ushort generation; /// /// Gets/sets Module.Name column /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// Gets/sets Module.Mvid column /// public Guid? Mvid { get { return mvid; } set { mvid = value; } } /// protected Guid? mvid; /// /// Gets/sets Module.EncId column /// public Guid? EncId { get { return encId; } set { encId = value; } } /// protected Guid? encId; /// /// Gets/sets Module.EncBaseId column /// public Guid? EncBaseId { get { return encBaseId; } set { encBaseId = value; } } /// protected Guid? encBaseId; /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public int HasCustomDebugInformationTag { get { return 7; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// /// Gets the module's assembly. To set this value, add this /// to . /// public AssemblyDef Assembly { get { return assembly; } internal set { assembly = value; } } /// protected AssemblyDef assembly; /// /// Gets a list of all non-nested s. See also /// public ThreadSafe.IList Types { get { if (types == null) InitializeTypes(); return types; } } /// protected LazyList types; /// Initializes protected virtual void InitializeTypes() { Interlocked.CompareExchange(ref types, new LazyList(this), null); } /// /// Gets a list of all s /// public ThreadSafe.IList ExportedTypes { get { if (exportedTypes == null) InitializeExportedTypes(); return exportedTypes; } } /// protected ThreadSafe.IList exportedTypes; /// Initializes protected virtual void InitializeExportedTypes() { Interlocked.CompareExchange(ref exportedTypes, ThreadSafeListCreator.Create(), null); } /// /// Gets/sets the native entry point. Only one of and /// can be set. You write to one and the other one gets cleared. /// public RVA NativeEntryPoint { get { if (!nativeAndManagedEntryPoint_initialized) InitializeNativeAndManagedEntryPoint(); return nativeEntryPoint; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif nativeEntryPoint = value; managedEntryPoint = null; Cor20HeaderFlags |= ComImageFlags.NativeEntryPoint; nativeAndManagedEntryPoint_initialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Gets/sets the managed entry point. Only one of and /// can be set. You write to one and the other one gets cleared. /// public IManagedEntryPoint ManagedEntryPoint { get { if (!nativeAndManagedEntryPoint_initialized) InitializeNativeAndManagedEntryPoint(); return managedEntryPoint; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif nativeEntryPoint = 0; managedEntryPoint = value; Cor20HeaderFlags &= ~ComImageFlags.NativeEntryPoint; nativeAndManagedEntryPoint_initialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected RVA nativeEntryPoint; /// protected IManagedEntryPoint managedEntryPoint; /// protected bool nativeAndManagedEntryPoint_initialized; void InitializeNativeAndManagedEntryPoint() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (nativeAndManagedEntryPoint_initialized) return; nativeEntryPoint = GetNativeEntryPoint_NoLock(); managedEntryPoint = GetManagedEntryPoint_NoLock(); nativeAndManagedEntryPoint_initialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual RVA GetNativeEntryPoint_NoLock() { return 0; } /// Called to initialize protected virtual IManagedEntryPoint GetManagedEntryPoint_NoLock() { return null; } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// /// Gets/sets the entry point method /// public MethodDef EntryPoint { get { return ManagedEntryPoint as MethodDef; } set { ManagedEntryPoint = value; } } /// /// true if is non-zero /// public bool IsNativeEntryPointValid { get { return NativeEntryPoint != 0; } } /// /// true if is non-null /// public bool IsManagedEntryPointValid { get { return ManagedEntryPoint != null; } } /// /// true if is non-null /// public bool IsEntryPointValid { get { return EntryPoint != null; } } /// /// Gets a list of all s /// public ResourceCollection Resources { get { if (resources == null) InitializeResources(); return resources; } } /// protected ResourceCollection resources; /// Initializes protected virtual void InitializeResources() { Interlocked.CompareExchange(ref resources, new ResourceCollection(), null); } /// /// Gets/sets the . This is null if there are no /// vtable fixups. /// public VTableFixups VTableFixups { get { if (!vtableFixups_isInitialized) InitializeVTableFixups(); return vtableFixups; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif vtableFixups = value; vtableFixups_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected VTableFixups vtableFixups; /// protected bool vtableFixups_isInitialized; void InitializeVTableFixups() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (vtableFixups_isInitialized) return; vtableFixups = GetVTableFixups_NoLock(); vtableFixups_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual VTableFixups GetVTableFixups_NoLock() { return null; } /// /// true if there's at least one in /// public bool HasTypes { get { return Types.Count > 0; } } /// /// true if there's at least one in /// public bool HasExportedTypes { get { return ExportedTypes.Count > 0; } } /// /// true if there's at least one in /// public bool HasResources { get { return Resources.Count > 0; } } /// public string FullName { get { return UTF8String.ToSystemStringOrEmpty(name); } } /// /// Gets/sets the path of the module or an empty string if it wasn't loaded from disk /// public string Location { get { return location; } set { location = value; } } /// protected string location; /// /// Gets the /// public ICorLibTypes CorLibTypes { get { return corLibTypes; } } /// /// Gets the instance /// TypeDefFinder TypeDefFinder { get { if (typeDefFinder == null) Interlocked.CompareExchange(ref typeDefFinder, new TypeDefFinder(Types), null); return typeDefFinder; } } /// /// Gets/sets the module context. This is never null. /// public ModuleContext Context { get { if (context == null) Interlocked.CompareExchange(ref context, new ModuleContext(), null); return context; } set { context = value ?? new ModuleContext(); } } /// /// If true, the cache is enabled. The cache is used by /// and to find types. ///

/// IMPORTANT: Only enable the cache if this module's types keep their exact /// name, namespace, and declaring type and if no type is either added or /// removed from or from any type that is reachable from the /// top-level types in (i.e., any type owned by this module). /// This is disabled by default. When disabled, all calls to /// and will result in a slow O(n) (linear) search. ///
/// public bool EnableTypeDefFindCache { get { return TypeDefFinder.IsCacheEnabled; } set { TypeDefFinder.IsCacheEnabled = value; } } /// /// true if this is the manifest (main) module /// public bool IsManifestModule { get { var asm = assembly; return asm != null && asm.ManifestModule == this; } } /// /// Gets the global (aka. <Module>) type or null if there are no types /// public TypeDef GlobalType { get { return Types.Get(0, null); } } /// /// true if it's the core library module, false if it's not the core library module, /// and null if it's not known. /// public bool? IsCoreLibraryModule { get; set; } /// /// Gets/sets the Win32 resources /// public Win32Resources Win32Resources { get { if (!win32Resources_isInitialized) InitializeWin32Resources(); return win32Resources; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif win32Resources = value; win32Resources_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected Win32Resources win32Resources; /// protected bool win32Resources_isInitialized; void InitializeWin32Resources() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (win32Resources_isInitialized) return; win32Resources = GetWin32Resources_NoLock(); win32Resources_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual Win32Resources GetWin32Resources_NoLock() { return null; } /// /// Gets the . This is null if no PDB file /// has been loaded or if no PDB file could be found. /// public PdbState PdbState { get { return pdbState; } } /// /// Module kind /// public ModuleKind Kind { get; set; } /// /// Gets/sets the characteristics (from PE file header) /// public Characteristics Characteristics { get; set; } /// /// Gets/sets the DLL characteristics (from PE optional header) /// public DllCharacteristics DllCharacteristics { get; set; } /// /// Gets/sets the runtime version which is stored in the MetaData header. /// See . /// /// Not thread safe public string RuntimeVersion { get { return runtimeVersion; } set { if (runtimeVersion != value) { runtimeVersion = value; cachedWinMDStatus = null; runtimeVersionWinMD = null; winMDVersion = null; } } } string runtimeVersion; /// /// Gets the WinMD status /// /// Not thread safe public WinMDStatus WinMDStatus { get { var cval = cachedWinMDStatus; if (cval != null) return cval.Value; cachedWinMDStatus = cval = CalculateWinMDStatus(RuntimeVersion); return cval.Value; } } WinMDStatus? cachedWinMDStatus; /// /// true if this is a WinMD file /// public bool IsWinMD { get { return WinMDStatus != WinMDStatus.None; } } /// /// true if this is a managed WinMD file /// public bool IsManagedWinMD { get { return WinMDStatus == WinMDStatus.Managed; } } /// /// true if this is a pure (non-managed) WinMD file /// public bool IsPureWinMD { get { return WinMDStatus == WinMDStatus.Pure; } } /// /// Gets the CLR runtime version of the managed WinMD file or null if none. This is /// similar to for normal non-WinMD files. /// /// Not thread safe public string RuntimeVersionWinMD { get { var rtver = runtimeVersionWinMD; if (rtver != null) return rtver; runtimeVersionWinMD = rtver = CalculateRuntimeVersionWinMD(RuntimeVersion); return rtver; } } string runtimeVersionWinMD; /// /// Gets the WinMD version or null if none /// /// Not thread safe public string WinMDVersion { get { var ver = winMDVersion; if (ver != null) return ver; winMDVersion = ver = CalculateWinMDVersion(RuntimeVersion); return ver; } } string winMDVersion; static WinMDStatus CalculateWinMDStatus(string version) { if (version == null) return WinMDStatus.None; if (!version.StartsWith("WindowsRuntime ", StringComparison.Ordinal)) return WinMDStatus.None; return version.IndexOf(';') < 0 ? WinMDStatus.Pure : WinMDStatus.Managed; } static string CalculateRuntimeVersionWinMD(string version) { // Original parser code: // CoreCLR file: src/md/winmd/adapter.cpp // Func: WinMDAdapter::Create(IMDCommon *pRawMDCommon, /*[out]*/ WinMDAdapter **ppAdapter) if (version == null) return null; if (!version.StartsWith("WindowsRuntime ", StringComparison.Ordinal)) return null; int index = version.IndexOf(';'); if (index < 0) return null; var s = version.Substring(index + 1); if (s.StartsWith("CLR", StringComparison.OrdinalIgnoreCase)) s = s.Substring(3); s = s.TrimStart(' '); return s; } static string CalculateWinMDVersion(string version) { if (version == null) return null; if (!version.StartsWith("WindowsRuntime ", StringComparison.Ordinal)) return null; int index = version.IndexOf(';'); if (index < 0) return version; return version.Substring(0, index); } /// /// true if is the CLR v1.0 string (only the major /// and minor version numbers are checked) /// public bool IsClr10 { get { var ver = RuntimeVersion ?? string.Empty; return ver.StartsWith(MDHeaderRuntimeVersion.MS_CLR_10_PREFIX) || ver.StartsWith(MDHeaderRuntimeVersion.MS_CLR_10_PREFIX_X86RETAIL) || ver == MDHeaderRuntimeVersion.MS_CLR_10_RETAIL || ver == MDHeaderRuntimeVersion.MS_CLR_10_COMPLUS; } } /// /// true if is the CLR v1.0 string /// public bool IsClr10Exactly { get { return RuntimeVersion == MDHeaderRuntimeVersion.MS_CLR_10 || RuntimeVersion == MDHeaderRuntimeVersion.MS_CLR_10_X86RETAIL || RuntimeVersion == MDHeaderRuntimeVersion.MS_CLR_10_RETAIL || RuntimeVersion == MDHeaderRuntimeVersion.MS_CLR_10_COMPLUS; } } /// /// true if is the CLR v1.1 string (only the major /// and minor version numbers are checked) /// public bool IsClr11 { get { return (RuntimeVersion ?? string.Empty).StartsWith(MDHeaderRuntimeVersion.MS_CLR_11_PREFIX); } } /// /// true if is the CLR v1.1 string /// public bool IsClr11Exactly { get { return RuntimeVersion == MDHeaderRuntimeVersion.MS_CLR_11; } } /// /// true if is the CLR v1.0 or v1.1 string (only the /// major and minor version numbers are checked) /// public bool IsClr1x { get { return IsClr10 || IsClr11; } } /// /// true if is the CLR v1.0 or v1.1 string /// public bool IsClr1xExactly { get { return IsClr10Exactly || IsClr11Exactly; } } /// /// true if is the CLR v2.0 string (only the major /// and minor version numbers are checked) /// public bool IsClr20 { get { return (RuntimeVersion ?? string.Empty).StartsWith(MDHeaderRuntimeVersion.MS_CLR_20_PREFIX); } } /// /// true if is the CLR v2.0 string /// public bool IsClr20Exactly { get { return RuntimeVersion == MDHeaderRuntimeVersion.MS_CLR_20; } } /// /// true if is the CLR v4.0 string (only the major /// and minor version numbers are checked) /// public bool IsClr40 { get { return (RuntimeVersion ?? string.Empty).StartsWith(MDHeaderRuntimeVersion.MS_CLR_40_PREFIX); } } /// /// true if is the CLR v4.0 string /// public bool IsClr40Exactly { get { return RuntimeVersion == MDHeaderRuntimeVersion.MS_CLR_40; } } /// /// true if is the ECMA 2002 string /// public bool IsEcma2002 { get { return RuntimeVersion == MDHeaderRuntimeVersion.ECMA_2002; } } /// /// true if is the ECMA 2005 string /// public bool IsEcma2005 { get { return RuntimeVersion == MDHeaderRuntimeVersion.ECMA_2005; } } /// /// Gets/sets the (from PE header) /// public Machine Machine { get; set; } /// /// true if is /// public bool IsI386 { get { return Machine == Machine.I386; } } /// /// true if is /// public bool IsIA64 { get { return Machine == Machine.IA64; } } /// /// true if is /// public bool IsAMD64 { get { return Machine == Machine.AMD64; } } /// /// true if is /// public bool IsARM64 { get { return Machine == Machine.ARM64; } } /// /// Gets/sets the (from .NET header) /// public ComImageFlags Cor20HeaderFlags { get { return (ComImageFlags)cor20HeaderFlags; } set { cor20HeaderFlags = (int)value; } } /// protected int cor20HeaderFlags; /// /// Gets/sets the runtime version number in the COR20 header. The major version is /// in the high 16 bits. The minor version is in the low 16 bits. This is normally 2.5 /// (0x00020005), but if it's .NET 1.x, it should be 2.0 (0x00020000). If this is /// null, the default value will be used when saving the module (2.0 if CLR 1.x, /// and 2.5 if not CLR 1.x). /// public uint? Cor20HeaderRuntimeVersion { get; set; } /// /// Gets the tables header version. The major version is in the upper 8 bits and the /// minor version is in the lower 8 bits. .NET 1.0/1.1 use version 1.0 (0x0100) and /// .NET 2.x and later use version 2.0 (0x0200). 1.0 has no support for generics, /// 1.1 has support for generics (GenericParam rows have an extra Kind column), /// and 2.0 has support for generics (GenericParam rows have the standard 4 columns). /// No other version is supported. If this is null, the default version is /// used (1.0 if .NET 1.x, else 2.0). /// public ushort? TablesHeaderVersion { get; set; } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyComImageFlags(bool set, ComImageFlags flags) { #if THREAD_SAFE int origVal, newVal; do { origVal = cor20HeaderFlags; if (set) newVal = origVal | (int)flags; else newVal = origVal & ~(int)flags; } while (Interlocked.CompareExchange(ref cor20HeaderFlags, newVal, origVal) != origVal); #else if (set) cor20HeaderFlags |= (int)flags; else cor20HeaderFlags &= ~(int)flags; #endif } /// /// Gets/sets the bit /// public bool IsILOnly { get { return ((ComImageFlags)cor20HeaderFlags & ComImageFlags.ILOnly) != 0; } set { ModifyComImageFlags(value, ComImageFlags.ILOnly); } } /// /// Gets/sets the bit /// public bool Is32BitRequired { get { return ((ComImageFlags)cor20HeaderFlags & ComImageFlags._32BitRequired) != 0; } set { ModifyComImageFlags(value, ComImageFlags._32BitRequired); } } /// /// Gets/sets the bit /// public bool IsStrongNameSigned { get { return ((ComImageFlags)cor20HeaderFlags & ComImageFlags.StrongNameSigned) != 0; } set { ModifyComImageFlags(value, ComImageFlags.StrongNameSigned); } } /// /// Gets/sets the bit /// public bool HasNativeEntryPoint { get { return ((ComImageFlags)cor20HeaderFlags & ComImageFlags.NativeEntryPoint) != 0; } set { ModifyComImageFlags(value, ComImageFlags.NativeEntryPoint); } } /// /// Gets/sets the bit /// public bool Is32BitPreferred { get { return ((ComImageFlags)cor20HeaderFlags & ComImageFlags._32BitPreferred) != 0; } set { ModifyComImageFlags(value, ComImageFlags._32BitPreferred); } } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose method /// /// true if called by protected virtual void Dispose(bool disposing) { if (!disposing) return; foreach (var resource in Resources.GetInitializedElements(true)) { if (resource != null) resource.Dispose(); } var tdf = typeDefFinder; if (tdf != null) { tdf.Dispose(); typeDefFinder = null; } var ps = pdbState; if (ps != null) ps.Dispose(); pdbState = null; } /// /// Gets all the types (including nested types) present in this module /// public IEnumerable GetTypes() { return AllTypesHelper.Types(Types); } /// /// Adds as a non-nested type. If it's already nested, its /// will be set to null. /// /// The to insert public void AddAsNonNestedType(TypeDef typeDef) { if (typeDef == null) return; typeDef.DeclaringType = null; Types.Add(typeDef); } /// /// Updates the rid to the next free rid available. It's only updated if /// the original rid is 0. /// /// IMDTokenProvider /// The row that should be updated /// Returns the input public T UpdateRowId(T tableRow) where T : IMDTokenProvider { if (tableRow != null && tableRow.Rid == 0) tableRow.Rid = GetNextFreeRid(tableRow.MDToken.Table); return tableRow; } /// /// Updates the rid to the next free rid available. /// /// IMDTokenProvider /// The row that should be updated /// Returns the input public T ForceUpdateRowId(T tableRow) where T : IMDTokenProvider { if (tableRow != null) tableRow.Rid = GetNextFreeRid(tableRow.MDToken.Table); return tableRow; } uint GetNextFreeRid(Table table) { var lastUsedRids = this.lastUsedRids; if ((uint)table >= lastUsedRids.Length) return 0; return (uint)Interlocked.Increment(ref lastUsedRids[(int)table]) & 0x00FFFFFF; } /// /// Imports a as a /// /// The type /// The imported type or null if is invalid public ITypeDefOrRef Import(Type type) { return new Importer(this).Import(type); } /// /// Imports a as a /// /// The type /// The imported type or null if is invalid public TypeSig ImportAsTypeSig(Type type) { return new Importer(this).ImportAsTypeSig(type); } /// /// Imports a as a /// /// The field /// The imported field or null if is invalid /// or if we failed to import the field public MemberRef Import(FieldInfo fieldInfo) { return (MemberRef)new Importer(this).Import(fieldInfo); } /// /// Imports a as a . This will be either /// a or a . /// /// The method /// The imported method or null if is invalid /// or if we failed to import the method public IMethod Import(MethodBase methodBase) { return new Importer(this).Import(methodBase); } /// /// Imports a /// /// The type /// The imported type or null public IType Import(IType type) { return new Importer(this).Import(type); } /// /// Imports a as a /// /// The type /// The imported type or null public TypeRef Import(TypeDef type) { return (TypeRef)new Importer(this).Import(type); } /// /// Imports a /// /// The type /// The imported type or null public TypeRef Import(TypeRef type) { return (TypeRef)new Importer(this).Import(type); } /// /// Imports a /// /// The type /// The imported type or null public TypeSpec Import(TypeSpec type) { return new Importer(this).Import(type); } /// /// Imports a /// /// The type /// The imported type or null public TypeSig Import(TypeSig type) { return new Importer(this).Import(type); } /// /// Imports a /// /// The field /// The imported type or null if is invalid public MemberRef Import(IField field) { return (MemberRef)new Importer(this).Import(field); } /// /// Imports a as a /// /// The field /// The imported type or null if is invalid public MemberRef Import(FieldDef field) { return (MemberRef)new Importer(this).Import(field); } /// /// Imports a /// /// The method /// The imported method or null if is invalid public IMethod Import(IMethod method) { return new Importer(this).Import(method); } /// /// Imports a as a /// /// The method /// The imported method or null if is invalid public MemberRef Import(MethodDef method) { return (MemberRef)new Importer(this).Import(method); } /// /// Imports a /// /// The method /// The imported method or null if is invalid public MethodSpec Import(MethodSpec method) { return new Importer(this).Import(method); } /// /// Imports a /// /// The member ref /// The imported member ref or null if is invalid public MemberRef Import(MemberRef memberRef) { return new Importer(this).Import(memberRef); } /// /// Writes the module to a file on disk. If the file exists, it will be overwritten. /// /// Filename public void Write(string filename) { Write(filename, null); } /// /// Writes the module to a file on disk. If the file exists, it will be overwritten. /// /// Filename /// Writer options public void Write(string filename, ModuleWriterOptions options) { var writer = new ModuleWriter(this, options ?? new ModuleWriterOptions(this)); writer.Write(filename); } /// /// Writes the module to a stream. /// /// Destination stream public void Write(Stream dest) { Write(dest, null); } /// /// Writes the module to a stream. /// /// Destination stream /// Writer options public void Write(Stream dest, ModuleWriterOptions options) { var writer = new ModuleWriter(this, options ?? new ModuleWriterOptions(this)); writer.Write(dest); } /// /// Resets the cache which can be enabled by setting /// to true. Use this method if the cache is /// enabled but some of the types have been modified (eg. removed, added, renamed). /// public void ResetTypeDefFindCache() { TypeDefFinder.ResetCache(); } /// /// Finds a /// /// Type /// Name /// Language ID /// The or null if none found public ResourceData FindWin32ResourceData(ResourceName type, ResourceName name, ResourceName langId) { var w32Resources = Win32Resources; return w32Resources == null ? null : w32Resources.Find(type, name, langId); } /// /// Creates a new /// /// PDB file kind public void CreatePdbState(PdbFileKind pdbFileKind) { SetPdbState(new PdbState(this, pdbFileKind)); } /// /// Sets a /// /// New public void SetPdbState(PdbState pdbState) { if (pdbState == null) throw new ArgumentNullException("pdbState"); var orig = Interlocked.CompareExchange(ref this.pdbState, pdbState, null); if (orig != null) throw new InvalidOperationException("PDB file has already been initialized"); } uint GetCor20RuntimeVersion() { var rtVer = Cor20HeaderRuntimeVersion; if (rtVer != null) return rtVer.Value; return IsClr1x ? 0x00020000U : 0x00020005; } /// /// Returns the size of a pointer. Assumes it's 32-bit if pointer size is unknown or /// if it can be 32-bit or 64-bit. /// /// Size of a pointer (4 or 8) public int GetPointerSize() { return GetPointerSize(4); } /// /// Returns the size of a pointer /// /// Default pointer size if it's not known or if it /// can be 32-bit or 64-bit /// Size of a pointer (4 or 8) public int GetPointerSize(int defaultPointerSize) { return GetPointerSize(defaultPointerSize, defaultPointerSize); } /// /// Returns the size of a pointer /// /// Default pointer size /// Pointer size if it's prefer-32-bit (should usually be 4) /// public int GetPointerSize(int defaultPointerSize, int prefer32bitPointerSize) { var machine = Machine; if (machine == Machine.AMD64 || machine == Machine.IA64 || machine == Machine.ARM64) return 8; if (machine != Machine.I386) return 4; // Machine is I386 so it's either x86 or platform neutral // If the runtime version is < 2.5, then it's always loaded as a 32-bit process. if (GetCor20RuntimeVersion() < 0x00020005) return 4; // If it's a 32-bit PE header, and ILOnly is cleared, it's always loaded as a // 32-bit process. var flags = (ComImageFlags)cor20HeaderFlags; if ((flags & ComImageFlags.ILOnly) == 0) return 4; // 32-bit Preferred flag is new in .NET 4.5. See CorHdr.h in Windows SDK for more info switch (flags & (ComImageFlags._32BitRequired | ComImageFlags._32BitPreferred)) { case 0: // Machine and ILOnly flag should be checked break; case ComImageFlags._32BitPreferred: // Illegal break; case ComImageFlags._32BitRequired: // x86 image (32-bit process) return 4; case ComImageFlags._32BitRequired | ComImageFlags._32BitPreferred: // Platform neutral but prefers to be 32-bit return prefer32bitPointerSize; } return defaultPointerSize; } /// void IListListener.OnLazyAdd(int index, ref TypeDef value) { #if DEBUG if (value.DeclaringType != null) throw new InvalidOperationException("Added type's DeclaringType != null"); #endif value.Module2 = this; } /// void IListListener.OnAdd(int index, TypeDef value) { if (value.DeclaringType != null) throw new InvalidOperationException("Nested type is already owned by another type. Set DeclaringType to null first."); if (value.Module != null) throw new InvalidOperationException("Type is already owned by another module. Remove it from that module's type list."); value.Module2 = this; } /// void IListListener.OnRemove(int index, TypeDef value) { value.Module2 = null; } /// void IListListener.OnResize(int index) { } /// void IListListener.OnClear() { foreach (var type in Types.GetEnumerable_NoLock()) type.Module2 = null; } /// /// Finds a . For speed, enable /// if possible (read the documentation first). /// /// Full name of the type (no assembly information) /// true if it's a reflection name, and nested /// type names are separated by a + character. If false, nested type names /// are separated by a / character. /// An existing or null if it wasn't found. public TypeDef Find(string fullName, bool isReflectionName) { return TypeDefFinder.Find(fullName, isReflectionName); } /// /// Finds a . Its scope (i.e., module or assembly) is ignored when /// looking up the type. For speed, enable if possible /// (read the documentation first). /// /// The type ref /// An existing or null if it wasn't found. public TypeDef Find(TypeRef typeRef) { return TypeDefFinder.Find(typeRef); } /// /// Finds a /// /// The type /// A or null if it wasn't found public TypeDef Find(ITypeDefOrRef typeRef) { var td = typeRef as TypeDef; if (td != null) return td.Module == this ? td : null; var tr = typeRef as TypeRef; if (tr != null) return Find(tr); var ts = typeRef as TypeSpec; if (ts == null) return null; var sig = ts.TypeSig as TypeDefOrRefSig; if (sig == null) return null; td = sig.TypeDef; if (td != null) return td.Module == this ? td : null; tr = sig.TypeRef; if (tr != null) return Find(tr); return null; } /// /// Creates a new instance. There should normally only be one /// instance shared by all s. /// /// If true, add other common assembly search /// paths, not just the module search paths and the GAC. /// A new instance public static ModuleContext CreateModuleContext(bool addOtherSearchPaths = true) { var ctx = new ModuleContext(); var asmRes = new AssemblyResolver(ctx, addOtherSearchPaths); var res = new Resolver(asmRes); ctx.AssemblyResolver = asmRes; ctx.Resolver = res; return ctx; } /// /// Load everything in this module. All types, fields, asm refs, etc are loaded, all their /// properties are read to make sure everything is cached. /// /// Cancellation token or null public virtual void LoadEverything(ICancellationToken cancellationToken = null) { ModuleLoader.LoadAll(this, cancellationToken); } /// public override string ToString() { return FullName; } /// /// Resolves a token /// /// The metadata token /// A or null if is invalid public IMDTokenProvider ResolveToken(MDToken mdToken) { return ResolveToken(mdToken.Raw, new GenericParamContext()); } /// /// Resolves a token /// /// The metadata token /// Generic parameter context /// A or null if is invalid public IMDTokenProvider ResolveToken(MDToken mdToken, GenericParamContext gpContext) { return ResolveToken(mdToken.Raw, gpContext); } /// /// Resolves a token /// /// The metadata token /// A or null if is invalid public IMDTokenProvider ResolveToken(int token) { return ResolveToken((uint)token, new GenericParamContext()); } /// /// Resolves a token /// /// The metadata token /// Generic parameter context /// A or null if is invalid public IMDTokenProvider ResolveToken(int token, GenericParamContext gpContext) { return ResolveToken((uint)token, gpContext); } /// /// Resolves a token /// /// The metadata token /// A or null if is invalid public IMDTokenProvider ResolveToken(uint token) { return ResolveToken(token, new GenericParamContext()); } /// /// Resolves a token /// /// The metadata token /// Generic parameter context /// A or null if is invalid public virtual IMDTokenProvider ResolveToken(uint token, GenericParamContext gpContext) { return null; } /// /// Gets all s /// public IEnumerable GetAssemblyRefs() { for (uint rid = 1; ; rid++) { var asmRef = ResolveToken(new MDToken(Table.AssemblyRef, rid).Raw) as AssemblyRef; if (asmRef == null) break; yield return asmRef; } } /// /// Gets all s /// public IEnumerable GetModuleRefs() { for (uint rid = 1; ; rid++) { var modRef = ResolveToken(new MDToken(Table.ModuleRef, rid).Raw) as ModuleRef; if (modRef == null) break; yield return modRef; } } /// /// Gets all s. s with generic parameters /// aren't cached and a new copy is always returned. /// public IEnumerable GetMemberRefs() { return GetMemberRefs(new GenericParamContext()); } /// /// Gets all s. s with generic parameters /// aren't cached and a new copy is always returned. /// /// Generic parameter context public IEnumerable GetMemberRefs(GenericParamContext gpContext) { for (uint rid = 1; ; rid++) { var mr = ResolveToken(new MDToken(Table.MemberRef, rid).Raw, gpContext) as MemberRef; if (mr == null) break; yield return mr; } } /// /// Gets all s /// public IEnumerable GetTypeRefs() { for (uint rid = 1; ; rid++) { var mr = ResolveToken(new MDToken(Table.TypeRef, rid).Raw) as TypeRef; if (mr == null) break; yield return mr; } } /// /// Finds an assembly reference by name. If there's more than one, pick the one with /// the greatest version number. /// /// Simple name of assembly (eg. "mscorlib") /// The found or null if there's no such /// assembly reference. public AssemblyRef GetAssemblyRef(UTF8String simpleName) { AssemblyRef found = null; foreach (var asmRef in GetAssemblyRefs()) { if (asmRef.Name != simpleName) continue; if (IsGreaterAssemblyRefVersion(found, asmRef)) found = asmRef; } return found; } /// /// Compare asm refs' version /// /// First asm ref /// New asm ref /// protected static bool IsGreaterAssemblyRefVersion(AssemblyRef found, AssemblyRef newOne) { if (found == null) return true; var foundVer = found.Version; var newVer = newOne.Version; return foundVer == null || (newVer != null && newVer >= foundVer); } ITypeDefOrRef ISignatureReaderHelper.ResolveTypeDefOrRef(uint codedToken, GenericParamContext gpContext) { uint token; if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token)) return null; return ResolveToken(token) as ITypeDefOrRef; } TypeSig ISignatureReaderHelper.ConvertRTInternalAddress(IntPtr address) { return null; } } /// /// A Module row created by the user and not present in the original .NET file /// public class ModuleDefUser : ModuleDef { /// /// Default constructor /// public ModuleDefUser() : this(null, null) { } /// /// Constructor /// /// is initialized to a random /// Module nam public ModuleDefUser(UTF8String name) : this(name, Guid.NewGuid()) { } /// /// Constructor /// /// Module name /// Module version ID public ModuleDefUser(UTF8String name, Guid? mvid) : this(name, mvid, null) { } /// /// Constructor /// /// Module name /// Module version ID /// Corlib assembly ref or null public ModuleDefUser(UTF8String name, Guid? mvid, AssemblyRef corLibAssemblyRef) { this.Kind = ModuleKind.Windows; this.Characteristics = DefaultCharacteristics; this.DllCharacteristics = DefaultDllCharacteristics; this.RuntimeVersion = MDHeaderRuntimeVersion.MS_CLR_20; this.Machine = Machine.I386; this.cor20HeaderFlags = (int)ComImageFlags.ILOnly; this.Cor20HeaderRuntimeVersion = 0x00020005; // .NET 2.0 or later should use 2.5 this.TablesHeaderVersion = 0x0200; // .NET 2.0 or later should use 2.0 this.types = new LazyList(this); this.exportedTypes = new LazyList(); this.resources = new ResourceCollection(); this.corLibTypes = new CorLibTypes(this, corLibAssemblyRef); this.types = new LazyList(this); this.name = name; this.mvid = mvid; types.Add(CreateModuleType()); UpdateRowId(this); } TypeDef CreateModuleType() { var type = UpdateRowId(new TypeDefUser(UTF8String.Empty, "", null)); type.Attributes = TypeAttributes.NotPublic | TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.AnsiClass; return type; } } /// /// Created from a row in the Module table /// public class ModuleDefMD2 : ModuleDef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.Module, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// protected override RVA GetNativeEntryPoint_NoLock() { return readerModule.GetNativeEntryPoint(); } /// protected override IManagedEntryPoint GetManagedEntryPoint_NoLock() { return readerModule.GetManagedEntryPoint(); } /// /// Constructor /// /// The module which contains this Module row /// Row ID /// If is null /// If is invalid internal ModuleDefMD2(ModuleDefMD readerModule, uint rid) { if (rid == 1 && readerModule == null) readerModule = (ModuleDefMD)this; #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (rid != 1 && readerModule.TablesStream.ModuleTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("Module rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; if (rid != 1) { this.Kind = ModuleKind.Windows; this.Characteristics = DefaultCharacteristics; this.DllCharacteristics = DefaultDllCharacteristics; this.RuntimeVersion = MDHeaderRuntimeVersion.MS_CLR_20; this.Machine = Machine.I386; this.cor20HeaderFlags = (int)ComImageFlags.ILOnly; this.Cor20HeaderRuntimeVersion = 0x00020005; // .NET 2.0 or later should use 2.5 this.TablesHeaderVersion = 0x0200; // .NET 2.0 or later should use 2.0 this.corLibTypes = new CorLibTypes(this); this.location = string.Empty; InitializeFromRawRow(); } } /// /// Initialize fields from the raw Module row /// protected void InitializeFromRawRow() { uint name, mvid, encId; uint encBaseId = readerModule.TablesStream.ReadModuleRow(origRid, out generation, out name, out mvid, out encId); this.mvid = readerModule.GuidStream.Read(mvid); this.encId = readerModule.GuidStream.Read(encId); this.encBaseId = readerModule.GuidStream.Read(encBaseId); this.name = readerModule.StringsStream.ReadNoNull(name); if (origRid == 1) assembly = readerModule.ResolveAssembly(origRid); } } } dnlib-2.1_VS2010/src/DotNet/ModuleDefMD.cs000066400000000000000000002407541325033663500200010ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Security; using System.Threading; using dnlib.PE; using dnlib.Utils; using dnlib.IO; using dnlib.DotNet.MD; using dnlib.DotNet.Emit; using dnlib.DotNet.Pdb; using dnlib.W32Resources; using DNW = dnlib.DotNet.Writer; using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet { /// /// Created from a row in the Module table /// public sealed class ModuleDefMD : ModuleDefMD2, IInstructionOperandResolver { /// The file that contains all .NET metadata MetaData metaData; IMethodDecrypter methodDecrypter; IStringDecrypter stringDecrypter; RandomRidList moduleRidList; SimpleLazyList listModuleDefMD; SimpleLazyList listTypeRefMD; SimpleLazyList listTypeDefMD; SimpleLazyList listFieldDefMD; SimpleLazyList listMethodDefMD; SimpleLazyList listParamDefMD; SimpleLazyList2 listInterfaceImplMD; SimpleLazyList2 listMemberRefMD; SimpleLazyList listConstantMD; SimpleLazyList listDeclSecurityMD; SimpleLazyList listClassLayoutMD; SimpleLazyList2 listStandAloneSigMD; SimpleLazyList listEventDefMD; SimpleLazyList listPropertyDefMD; SimpleLazyList listModuleRefMD; SimpleLazyList2 listTypeSpecMD; SimpleLazyList listImplMapMD; SimpleLazyList listAssemblyDefMD; SimpleLazyList listAssemblyRefMD; SimpleLazyList listFileDefMD; SimpleLazyList listExportedTypeMD; SimpleLazyList listManifestResourceMD; SimpleLazyList listGenericParamMD; SimpleLazyList2 listMethodSpecMD; SimpleLazyList2 listGenericParamConstraintMD; /// /// Gets/sets the method decrypter /// public IMethodDecrypter MethodDecrypter { get { return methodDecrypter; } set { methodDecrypter = value; } } /// /// Gets/sets the string decrypter /// public IStringDecrypter StringDecrypter { get { return stringDecrypter; } set { stringDecrypter = value; } } /// /// Returns the .NET metadata interface /// public IMetaData MetaData { get { return metaData; } } /// /// Returns the #~ or #- tables stream /// public TablesStream TablesStream { get { return metaData.TablesStream; } } /// /// Returns the #Strings stream /// public StringsStream StringsStream { get { return metaData.StringsStream; } } /// /// Returns the #Blob stream /// public BlobStream BlobStream { get { return metaData.BlobStream; } } /// /// Returns the #GUID stream /// public GuidStream GuidStream { get { return metaData.GuidStream; } } /// /// Returns the #US stream /// public USStream USStream { get { return metaData.USStream; } } /// protected override void InitializeTypes() { var list = MetaData.GetNonNestedClassRidList(); var tmp = new LazyList((int)list.Length, this, list, (list2, index) => ResolveTypeDef(((RidList)list2)[index])); Interlocked.CompareExchange(ref types, tmp, null); } /// protected override void InitializeExportedTypes() { var list = MetaData.GetExportedTypeRidList(); var tmp = new LazyList((int)list.Length, list, (list2, i) => ResolveExportedType(((RidList)list2)[i])); Interlocked.CompareExchange(ref exportedTypes, tmp, null); } /// protected override void InitializeResources() { var table = TablesStream.ManifestResourceTable; var tmp = new ResourceCollection((int)table.Rows, null, (ctx, i) => CreateResource(i + 1)); Interlocked.CompareExchange(ref resources, tmp, null); } /// protected override Win32Resources GetWin32Resources_NoLock() { return metaData.PEImage.Win32Resources; } /// protected override VTableFixups GetVTableFixups_NoLock() { var vtableFixupsInfo = metaData.ImageCor20Header.VTableFixups; if (vtableFixupsInfo.VirtualAddress == 0 || vtableFixupsInfo.Size == 0) return null; return new VTableFixups(this); } /// /// Creates a instance from a file /// /// File name of an existing .NET module/assembly /// Module context or null /// A new instance public static ModuleDefMD Load(string fileName, ModuleContext context) { return Load(fileName, new ModuleCreationOptions(context)); } /// /// Creates a instance from a file /// /// File name of an existing .NET module/assembly /// Module creation options or null /// A new instance public static ModuleDefMD Load(string fileName, ModuleCreationOptions options = null) { return Load(MetaDataCreator.Load(fileName), options); } /// /// Creates a instance from a byte[] /// /// Contents of a .NET module/assembly /// Module context or null /// A new instance public static ModuleDefMD Load(byte[] data, ModuleContext context) { return Load(data, new ModuleCreationOptions(context)); } /// /// Creates a instance from a byte[] /// /// Contents of a .NET module/assembly /// Module creation options or null /// A new instance public static ModuleDefMD Load(byte[] data, ModuleCreationOptions options = null) { return Load(MetaDataCreator.Load(data), options); } /// /// Creates a instance from a reflection module /// /// An existing reflection module /// A new instance public static ModuleDefMD Load(System.Reflection.Module mod) { return Load(mod, (ModuleCreationOptions)null, GetImageLayout(mod)); } /// /// Creates a instance from a reflection module /// /// An existing reflection module /// Module context or null /// A new instance public static ModuleDefMD Load(System.Reflection.Module mod, ModuleContext context) { return Load(mod, new ModuleCreationOptions(context), GetImageLayout(mod)); } /// /// Creates a instance from a reflection module /// /// An existing reflection module /// Module creation options or null /// A new instance public static ModuleDefMD Load(System.Reflection.Module mod, ModuleCreationOptions options) { return Load(mod, options, GetImageLayout(mod)); } static ImageLayout GetImageLayout(System.Reflection.Module mod) { var fqn = mod.FullyQualifiedName; if (fqn.Length > 0 && fqn[0] == '<' && fqn[fqn.Length - 1] == '>') return ImageLayout.File; return ImageLayout.Memory; } /// /// Creates a instance from a reflection module /// /// An existing reflection module /// Module context or null /// Image layout of the module in memory /// A new instance public static ModuleDefMD Load(System.Reflection.Module mod, ModuleContext context, ImageLayout imageLayout) { return Load(mod, new ModuleCreationOptions(context), imageLayout); } static IntPtr GetModuleHandle(System.Reflection.Module mod) { #if NETSTANDARD2_0 var GetHINSTANCE = typeof(Marshal).GetMethod("GetHINSTANCE", new[] { typeof(System.Reflection.Module) }); if (GetHINSTANCE == null) throw new NotSupportedException("System.Reflection.Module loading is not supported on current platform"); var addr = (IntPtr)GetHINSTANCE.Invoke(null, new[] { mod }); #else var addr = Marshal.GetHINSTANCE(mod); #endif if (addr == IntPtr.Zero || addr == new IntPtr(-1)) throw new ArgumentException("It is not possible to get address of module"); return addr; } /// /// Creates a instance from a reflection module /// /// An existing reflection module /// Module creation options or null /// Image layout of the module in memory /// A new instance public static ModuleDefMD Load(System.Reflection.Module mod, ModuleCreationOptions options, ImageLayout imageLayout) { IntPtr addr = GetModuleHandle(mod); if (addr == new IntPtr(-1)) throw new InvalidOperationException(string.Format("Module {0} has no HINSTANCE", mod)); return Load(addr, options, imageLayout); } /// /// Creates a instance from a memory location /// /// Address of a .NET module/assembly /// A new instance public static ModuleDefMD Load(IntPtr addr) { return Load(MetaDataCreator.Load(addr), (ModuleCreationOptions)null); } /// /// Creates a instance from a memory location /// /// Address of a .NET module/assembly /// Module context or null /// A new instance public static ModuleDefMD Load(IntPtr addr, ModuleContext context) { return Load(MetaDataCreator.Load(addr), new ModuleCreationOptions(context)); } /// /// Creates a instance from a memory location /// /// Address of a .NET module/assembly /// Module creation options or null /// A new instance public static ModuleDefMD Load(IntPtr addr, ModuleCreationOptions options) { return Load(MetaDataCreator.Load(addr), options); } /// /// Creates a instance /// /// PE image /// A new instance public static ModuleDefMD Load(IPEImage peImage) { return Load(MetaDataCreator.Load(peImage), (ModuleCreationOptions)null); } /// /// Creates a instance /// /// PE image /// Module context or null /// A new instance public static ModuleDefMD Load(IPEImage peImage, ModuleContext context) { return Load(MetaDataCreator.Load(peImage), new ModuleCreationOptions(context)); } /// /// Creates a instance /// /// PE image /// Module creation options or null /// A new instance public static ModuleDefMD Load(IPEImage peImage, ModuleCreationOptions options) { return Load(MetaDataCreator.Load(peImage), options); } /// /// Creates a instance from a memory location /// /// Address of a .NET module/assembly /// Module context or null /// Image layout of the file in memory /// A new instance public static ModuleDefMD Load(IntPtr addr, ModuleContext context, ImageLayout imageLayout) { return Load(MetaDataCreator.Load(addr, imageLayout), new ModuleCreationOptions(context)); } /// /// Creates a instance from a memory location /// /// Address of a .NET module/assembly /// Module creation options or null /// Image layout of the file in memory /// A new instance public static ModuleDefMD Load(IntPtr addr, ModuleCreationOptions options, ImageLayout imageLayout) { return Load(MetaDataCreator.Load(addr, imageLayout), options); } /// /// Creates a 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 (owned by caller) /// A new instance /// If is null public static ModuleDefMD Load(Stream stream) { return Load(stream, (ModuleCreationOptions)null); } /// /// Creates a 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 (owned by caller) /// Module context or null /// A new instance /// If is null public static ModuleDefMD Load(Stream stream, ModuleContext context) { return Load(stream, new ModuleCreationOptions(context)); } /// /// Creates a 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 (owned by caller) /// Module creation options or null /// A new instance /// If is null public static ModuleDefMD Load(Stream stream, ModuleCreationOptions options) { if (stream == null) throw new ArgumentNullException("stream"); if (stream.Length > int.MaxValue) throw new ArgumentException("Stream is too big"); var data = new byte[(int)stream.Length]; stream.Position = 0; if (stream.Read(data, 0, data.Length) != data.Length) throw new IOException("Could not read all bytes from the stream"); return Load(data, options); } /// /// Creates a instance from a /// /// The metadata /// Module creation options or null /// A new instance that now owns internal static ModuleDefMD Load(MetaData metaData, ModuleCreationOptions options) { return new ModuleDefMD(metaData, options); } /// /// Constructor /// /// The metadata /// Module creation options or null /// If is null ModuleDefMD(MetaData metaData, ModuleCreationOptions options) : base(null, 1) { #if DEBUG if (metaData == null) throw new ArgumentNullException("metaData"); #endif if (options == null) options = ModuleCreationOptions.Default; this.metaData = metaData; this.context = options.Context; Initialize(); InitializeFromRawRow(); location = metaData.PEImage.FileName ?? string.Empty; this.Kind = GetKind(); this.Characteristics = MetaData.PEImage.ImageNTHeaders.FileHeader.Characteristics; this.DllCharacteristics = MetaData.PEImage.ImageNTHeaders.OptionalHeader.DllCharacteristics; this.RuntimeVersion = MetaData.VersionString; this.Machine = MetaData.PEImage.ImageNTHeaders.FileHeader.Machine; this.Cor20HeaderFlags = MetaData.ImageCor20Header.Flags; this.Cor20HeaderRuntimeVersion = (uint)(MetaData.ImageCor20Header.MajorRuntimeVersion << 16) | MetaData.ImageCor20Header.MinorRuntimeVersion; this.TablesHeaderVersion = MetaData.TablesStream.Version; corLibTypes = new CorLibTypes(this, options.CorLibAssemblyRef ?? FindCorLibAssemblyRef() ?? CreateDefaultCorLibAssemblyRef()); InitializePdb(options); } void InitializePdb(ModuleCreationOptions options) { if (options == null) return; LoadPdb(CreateSymbolReader(options)); } SymbolReader CreateSymbolReader(ModuleCreationOptions options) { if (options.CreateSymbolReader != null) { var symReader = options.CreateSymbolReader(this); if (symReader != null) return symReader; } if (options.PdbFileOrData != null) { var pdbFileName = options.PdbFileOrData as string; if (!string.IsNullOrEmpty(pdbFileName)) { var symReader = SymbolReaderCreator.Create(options.PdbImplementation, metaData, pdbFileName); if (symReader != null) return symReader; } var pdbData = options.PdbFileOrData as byte[]; if (pdbData != null) return SymbolReaderCreator.Create(options.PdbImplementation, metaData, pdbData); var pdbStream = options.PdbFileOrData as IImageStream; if (pdbStream != null) return SymbolReaderCreator.Create(options.PdbImplementation, metaData, pdbStream); } if (options.TryToLoadPdbFromDisk) { if (!string.IsNullOrEmpty(location)) return SymbolReaderCreator.CreateFromAssemblyFile(options.PdbImplementation, metaData, location); else return SymbolReaderCreator.Create(options.PdbImplementation, metaData); } return null; } /// /// Loads symbols using /// /// PDB symbol reader public void LoadPdb(SymbolReader symbolReader) { if (symbolReader == null) return; if (pdbState != null) throw new InvalidOperationException("PDB file has already been initialized"); var orig = Interlocked.CompareExchange(ref pdbState, new PdbState(symbolReader, this), null); if (orig != null) throw new InvalidOperationException("PDB file has already been initialized"); } /// /// Loads symbols from a PDB file /// /// PDB file name public void LoadPdb(string pdbFileName) { LoadPdb(PdbImplType.Default, pdbFileName); } /// /// Loads symbols from a PDB file /// /// PDB implementation to use /// PDB file name public void LoadPdb(PdbImplType pdbImpl, string pdbFileName) { LoadPdb(SymbolReaderCreator.Create(pdbImpl, metaData, pdbFileName)); } /// /// Loads symbols from a byte array /// /// PDB data public void LoadPdb(byte[] pdbData) { LoadPdb(PdbImplType.Default, pdbData); } /// /// Loads symbols from a byte array /// /// PDB implementation to use /// PDB data public void LoadPdb(PdbImplType pdbImpl, byte[] pdbData) { LoadPdb(SymbolReaderCreator.Create(pdbImpl, metaData, pdbData)); } /// /// Loads symbols from a stream /// /// PDB file stream which is now owned by us public void LoadPdb(IImageStream pdbStream) { LoadPdb(PdbImplType.Default, pdbStream); } /// /// Loads symbols from a stream /// /// PDB implementation to use /// PDB file stream which is now owned by us public void LoadPdb(PdbImplType pdbImpl, IImageStream pdbStream) { LoadPdb(SymbolReaderCreator.Create(pdbImpl, metaData, pdbStream)); } /// /// Loads symbols if a PDB file is available /// public void LoadPdb() { LoadPdb(PdbImplType.Default); } /// /// Loads symbols if a PDB file is available /// /// PDB implementation to use public void LoadPdb(PdbImplType pdbImpl) { var loc = location; if (string.IsNullOrEmpty(loc)) return; LoadPdb(SymbolReaderCreator.Create(pdbImpl, metaData, loc)); } internal void InitializeCustomDebugInfos(MDToken token, GenericParamContext gpContext, IList result) { var ps = pdbState; if (ps == null) return; ps.InitializeCustomDebugInfos(token, gpContext, result); } ModuleKind GetKind() { if (TablesStream.AssemblyTable.Rows < 1) return ModuleKind.NetModule; var peImage = MetaData.PEImage; if ((peImage.ImageNTHeaders.FileHeader.Characteristics & Characteristics.Dll) != 0) return ModuleKind.Dll; switch (peImage.ImageNTHeaders.OptionalHeader.Subsystem) { default: case Subsystem.WindowsGui: return ModuleKind.Windows; case Subsystem.WindowsCui: return ModuleKind.Console; } } void Initialize() { var ts = metaData.TablesStream; listModuleDefMD = new SimpleLazyList(ts.ModuleTable.Rows, rid2 => rid2 == 1 ? this : new ModuleDefMD2(this, rid2)); listTypeRefMD = new SimpleLazyList(ts.TypeRefTable.Rows, rid2 => new TypeRefMD(this, rid2)); listTypeDefMD = new SimpleLazyList(ts.TypeDefTable.Rows, rid2 => new TypeDefMD(this, rid2)); listFieldDefMD = new SimpleLazyList(ts.FieldTable.Rows, rid2 => new FieldDefMD(this, rid2)); listMethodDefMD = new SimpleLazyList(ts.MethodTable.Rows, rid2 => new MethodDefMD(this, rid2)); listParamDefMD = new SimpleLazyList(ts.ParamTable.Rows, rid2 => new ParamDefMD(this, rid2)); listInterfaceImplMD = new SimpleLazyList2(ts.InterfaceImplTable.Rows, (rid2, gpContext) => new InterfaceImplMD(this, rid2, gpContext)); listMemberRefMD = new SimpleLazyList2(ts.MemberRefTable.Rows, (rid2, gpContext) => new MemberRefMD(this, rid2, gpContext)); listConstantMD = new SimpleLazyList(ts.ConstantTable.Rows, rid2 => new ConstantMD(this, rid2)); listDeclSecurityMD = new SimpleLazyList(ts.DeclSecurityTable.Rows, rid2 => new DeclSecurityMD(this, rid2)); listClassLayoutMD = new SimpleLazyList(ts.ClassLayoutTable.Rows, rid2 => new ClassLayoutMD(this, rid2)); listStandAloneSigMD = new SimpleLazyList2(ts.StandAloneSigTable.Rows, (rid2, gpContext) => new StandAloneSigMD(this, rid2, gpContext)); listEventDefMD = new SimpleLazyList(ts.EventTable.Rows, rid2 => new EventDefMD(this, rid2)); listPropertyDefMD = new SimpleLazyList(ts.PropertyTable.Rows, rid2 => new PropertyDefMD(this, rid2)); listModuleRefMD = new SimpleLazyList(ts.ModuleRefTable.Rows, rid2 => new ModuleRefMD(this, rid2)); listTypeSpecMD = new SimpleLazyList2(ts.TypeSpecTable.Rows, (rid2, gpContext) => new TypeSpecMD(this, rid2, gpContext)); listImplMapMD = new SimpleLazyList(ts.ImplMapTable.Rows, rid2 => new ImplMapMD(this, rid2)); listAssemblyDefMD = new SimpleLazyList(ts.AssemblyTable.Rows, rid2 => new AssemblyDefMD(this, rid2)); listFileDefMD = new SimpleLazyList(ts.FileTable.Rows, rid2 => new FileDefMD(this, rid2)); listAssemblyRefMD = new SimpleLazyList(ts.AssemblyRefTable.Rows, rid2 => new AssemblyRefMD(this, rid2)); listExportedTypeMD = new SimpleLazyList(ts.ExportedTypeTable.Rows, rid2 => new ExportedTypeMD(this, rid2)); listManifestResourceMD = new SimpleLazyList(ts.ManifestResourceTable.Rows, rid2 => new ManifestResourceMD(this, rid2)); listGenericParamMD = new SimpleLazyList(ts.GenericParamTable.Rows, rid2 => new GenericParamMD(this, rid2)); listMethodSpecMD = new SimpleLazyList2(ts.MethodSpecTable.Rows, (rid2, gpContext) => new MethodSpecMD(this, rid2, gpContext)); listGenericParamConstraintMD = new SimpleLazyList2(ts.GenericParamConstraintTable.Rows, (rid2, gpContext) => new GenericParamConstraintMD(this, rid2, gpContext)); for (int i = 0; i < 64; i++) { var tbl = TablesStream.Get((Table)i); lastUsedRids[i] = tbl == null ? 0 : (int)tbl.Rows; } } static readonly Dictionary preferredCorLibs = new Dictionary(StringComparer.OrdinalIgnoreCase) { // .NET Framework { "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 100 }, { "mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 90 }, { "mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 60 }, { "mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 50 }, // Silverlight { "mscorlib, Version=5.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", 80 }, { "mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", 70 }, // Zune { "mscorlib, Version=3.5.0.0, Culture=neutral, PublicKeyToken=e92a8b81eba7ceb7", 60 }, // Compact Framework { "mscorlib, Version=3.5.0.0, Culture=neutral, PublicKeyToken=969db8053d3322ac", 60 }, { "mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=969db8053d3322ac", 50 }, }; /// /// Finds a mscorlib /// /// An existing instance or null if it wasn't found AssemblyRef FindCorLibAssemblyRef() { var numAsmRefs = TablesStream.AssemblyRefTable.Rows; AssemblyRef corLibAsmRef = null; int currentPriority = int.MinValue; for (uint i = 1; i <= numAsmRefs; i++) { var asmRef = ResolveAssemblyRef(i); int priority; if (!preferredCorLibs.TryGetValue(asmRef.FullName, out priority)) continue; if (priority > currentPriority) { currentPriority = priority; corLibAsmRef = asmRef; } } if (corLibAsmRef != null) return corLibAsmRef; for (uint i = 1; i <= numAsmRefs; i++) { var asmRef = ResolveAssemblyRef(i); if (!UTF8String.ToSystemStringOrEmpty(asmRef.Name).Equals("netstandard", StringComparison.OrdinalIgnoreCase)) continue; if (IsGreaterAssemblyRefVersion(corLibAsmRef, asmRef)) corLibAsmRef = asmRef; } if (corLibAsmRef != null) return corLibAsmRef; for (uint i = 1; i <= numAsmRefs; i++) { var asmRef = ResolveAssemblyRef(i); if (!UTF8String.ToSystemStringOrEmpty(asmRef.Name).Equals("mscorlib", StringComparison.OrdinalIgnoreCase)) continue; if (IsGreaterAssemblyRefVersion(corLibAsmRef, asmRef)) corLibAsmRef = asmRef; } if (corLibAsmRef != null) return corLibAsmRef; // If we've loaded mscorlib itself, it won't have any AssemblyRefs to itself. var asm = Assembly; if (asm != null && (asm.IsCorLib() || Find("System.Object", false) != null)) { IsCoreLibraryModule = true; return UpdateRowId(new AssemblyRefUser(asm)); } return corLibAsmRef; } /// /// Called when no corlib assembly reference was found /// /// AssemblyRef CreateDefaultCorLibAssemblyRef() { var asmRef = GetAlternativeCorLibReference(); if (asmRef != null) return UpdateRowId(asmRef); if (this.IsClr40) return UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR40()); if (this.IsClr20) return UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR20()); if (this.IsClr11) return UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR11()); if (this.IsClr10) return UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR10()); return UpdateRowId(AssemblyRefUser.CreateMscorlibReferenceCLR40()); } AssemblyRef GetAlternativeCorLibReference() { foreach (var asmRef in GetAssemblyRefs()) { if (IsAssemblyRef(asmRef, systemRuntimeName, contractsPublicKeyToken)) return asmRef; } foreach (var asmRef in GetAssemblyRefs()) { if (IsAssemblyRef(asmRef, corefxName, contractsPublicKeyToken)) return asmRef; } return null; } static bool IsAssemblyRef(AssemblyRef asmRef, UTF8String name, PublicKeyToken token) { if (asmRef.Name != name) return false; var pkot = asmRef.PublicKeyOrToken; if (pkot == null) return false; return token.Equals(pkot.Token); } static readonly UTF8String systemRuntimeName = new UTF8String("System.Runtime"); static readonly UTF8String corefxName = new UTF8String("corefx"); static readonly PublicKeyToken contractsPublicKeyToken = new PublicKeyToken("b03f5f7f11d50a3a"); /// protected override void Dispose(bool disposing) { // Call base first since it will dispose of all the resources, which will // eventually use metaData that we will dispose base.Dispose(disposing); if (disposing) { var md = metaData; if (md != null) md.Dispose(); metaData = null; } } /// /// Resolves a token /// /// The metadata token /// Generic parameter context /// A or null if is invalid public override IMDTokenProvider ResolveToken(uint token, GenericParamContext gpContext) { uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.Module: return ResolveModule(rid); case Table.TypeRef: return ResolveTypeRef(rid); case Table.TypeDef: return ResolveTypeDef(rid); case Table.Field: return ResolveField(rid); case Table.Method: return ResolveMethod(rid); case Table.Param: return ResolveParam(rid); case Table.InterfaceImpl: return ResolveInterfaceImpl(rid, gpContext); case Table.MemberRef: return ResolveMemberRef(rid, gpContext); case Table.Constant: return ResolveConstant(rid); case Table.DeclSecurity: return ResolveDeclSecurity(rid); case Table.ClassLayout: return ResolveClassLayout(rid); case Table.StandAloneSig: return ResolveStandAloneSig(rid, gpContext); case Table.Event: return ResolveEvent(rid); case Table.Property: return ResolveProperty(rid); case Table.ModuleRef: return ResolveModuleRef(rid); case Table.TypeSpec: return ResolveTypeSpec(rid, gpContext); case Table.ImplMap: return ResolveImplMap(rid); case Table.Assembly: return ResolveAssembly(rid); case Table.AssemblyRef: return ResolveAssemblyRef(rid); case Table.File: return ResolveFile(rid); case Table.ExportedType: return ResolveExportedType(rid); case Table.ManifestResource:return ResolveManifestResource(rid); case Table.GenericParam: return ResolveGenericParam(rid); case Table.MethodSpec: return ResolveMethodSpec(rid, gpContext); case Table.GenericParamConstraint: return ResolveGenericParamConstraint(rid, gpContext); } return null; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public ModuleDef ResolveModule(uint rid) { return listModuleDefMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public TypeRef ResolveTypeRef(uint rid) { return listTypeRefMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public TypeDef ResolveTypeDef(uint rid) { return listTypeDefMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public FieldDef ResolveField(uint rid) { return listFieldDefMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public MethodDef ResolveMethod(uint rid) { return listMethodDefMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public ParamDef ResolveParam(uint rid) { return listParamDefMD[rid - 1]; } /// /// Resolves an /// /// The row ID /// A instance or null if is invalid public InterfaceImpl ResolveInterfaceImpl(uint rid) { return listInterfaceImplMD[rid - 1, new GenericParamContext()]; } /// /// Resolves an /// /// The row ID /// Generic parameter context /// A instance or null if is invalid public InterfaceImpl ResolveInterfaceImpl(uint rid, GenericParamContext gpContext) { return listInterfaceImplMD[rid - 1, gpContext]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public MemberRef ResolveMemberRef(uint rid) { return listMemberRefMD[rid - 1, new GenericParamContext()]; } /// /// Resolves a /// /// The row ID /// Generic parameter context /// A instance or null if is invalid public MemberRef ResolveMemberRef(uint rid, GenericParamContext gpContext) { return listMemberRefMD[rid - 1, gpContext]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public Constant ResolveConstant(uint rid) { return listConstantMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public DeclSecurity ResolveDeclSecurity(uint rid) { return listDeclSecurityMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public ClassLayout ResolveClassLayout(uint rid) { return listClassLayoutMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public StandAloneSig ResolveStandAloneSig(uint rid) { return listStandAloneSigMD[rid - 1, new GenericParamContext()]; } /// /// Resolves a /// /// The row ID /// Generic parameter context /// A instance or null if is invalid public StandAloneSig ResolveStandAloneSig(uint rid, GenericParamContext gpContext) { return listStandAloneSigMD[rid - 1, gpContext]; } /// /// Resolves an /// /// The row ID /// A instance or null if is invalid public EventDef ResolveEvent(uint rid) { return listEventDefMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public PropertyDef ResolveProperty(uint rid) { return listPropertyDefMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public ModuleRef ResolveModuleRef(uint rid) { return listModuleRefMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public TypeSpec ResolveTypeSpec(uint rid) { return listTypeSpecMD[rid - 1, new GenericParamContext()]; } /// /// Resolves a /// /// The row ID /// Generic parameter context /// A instance or null if is invalid public TypeSpec ResolveTypeSpec(uint rid, GenericParamContext gpContext) { return listTypeSpecMD[rid - 1, gpContext]; } /// /// Resolves an /// /// The row ID /// A instance or null if is invalid public ImplMap ResolveImplMap(uint rid) { return listImplMapMD[rid - 1]; } /// /// Resolves an /// /// The row ID /// A instance or null if is invalid public AssemblyDef ResolveAssembly(uint rid) { return listAssemblyDefMD[rid - 1]; } /// /// Resolves an /// /// The row ID /// A instance or null if is invalid public AssemblyRef ResolveAssemblyRef(uint rid) { return listAssemblyRefMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public FileDef ResolveFile(uint rid) { return listFileDefMD[rid - 1]; } /// /// Resolves an /// /// The row ID /// A instance or null if is invalid public ExportedType ResolveExportedType(uint rid) { return listExportedTypeMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public ManifestResource ResolveManifestResource(uint rid) { return listManifestResourceMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public GenericParam ResolveGenericParam(uint rid) { return listGenericParamMD[rid - 1]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public MethodSpec ResolveMethodSpec(uint rid) { return listMethodSpecMD[rid - 1, new GenericParamContext()]; } /// /// Resolves a /// /// The row ID /// Generic parameter context /// A instance or null if is invalid public MethodSpec ResolveMethodSpec(uint rid, GenericParamContext gpContext) { return listMethodSpecMD[rid - 1, gpContext]; } /// /// Resolves a /// /// The row ID /// A instance or null if is invalid public GenericParamConstraint ResolveGenericParamConstraint(uint rid) { return listGenericParamConstraintMD[rid - 1, new GenericParamContext()]; } /// /// Resolves a /// /// The row ID /// Generic parameter context /// A instance or null if is invalid public GenericParamConstraint ResolveGenericParamConstraint(uint rid, GenericParamContext gpContext) { return listGenericParamConstraintMD[rid - 1, gpContext]; } /// /// Resolves a /// /// A TypeDefOrRef coded token /// A or null if is invalid public ITypeDefOrRef ResolveTypeDefOrRef(uint codedToken) { return ResolveTypeDefOrRef(codedToken, new GenericParamContext()); } /// /// Resolves a /// /// A TypeDefOrRef coded token /// Generic parameter context /// A or null if is invalid public ITypeDefOrRef ResolveTypeDefOrRef(uint codedToken, GenericParamContext gpContext) { uint token; if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.TypeDef: return ResolveTypeDef(rid); case Table.TypeRef: return ResolveTypeRef(rid); case Table.TypeSpec: return ResolveTypeSpec(rid, gpContext); } return null; } /// /// Resolves a /// /// A HasConstant coded token /// A or null if is invalid public IHasConstant ResolveHasConstant(uint codedToken) { uint token; if (!CodedToken.HasConstant.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.Field: return ResolveField(rid); case Table.Param: return ResolveParam(rid); case Table.Property:return ResolveProperty(rid); } return null; } /// /// Resolves a /// /// A HasCustomAttribute coded token /// A or null if is invalid public IHasCustomAttribute ResolveHasCustomAttribute(uint codedToken) { return ResolveHasCustomAttribute(codedToken, new GenericParamContext()); } /// /// Resolves a /// /// A HasCustomAttribute coded token /// Generic parameter context /// A or null if is invalid public IHasCustomAttribute ResolveHasCustomAttribute(uint codedToken, GenericParamContext gpContext) { uint token; if (!CodedToken.HasCustomAttribute.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.Method: return ResolveMethod(rid); case Table.Field: return ResolveField(rid); case Table.TypeRef: return ResolveTypeRef(rid); case Table.TypeDef: return ResolveTypeDef(rid); case Table.Param: return ResolveParam(rid); case Table.InterfaceImpl: return ResolveInterfaceImpl(rid, gpContext); case Table.MemberRef: return ResolveMemberRef(rid, gpContext); case Table.Module: return ResolveModule(rid); case Table.DeclSecurity:return ResolveDeclSecurity(rid); case Table.Property: return ResolveProperty(rid); case Table.Event: return ResolveEvent(rid); case Table.StandAloneSig: return ResolveStandAloneSig(rid, gpContext); case Table.ModuleRef: return ResolveModuleRef(rid); case Table.TypeSpec: return ResolveTypeSpec(rid, gpContext); case Table.Assembly: return ResolveAssembly(rid); case Table.AssemblyRef: return ResolveAssemblyRef(rid); case Table.File: return ResolveFile(rid); case Table.ExportedType:return ResolveExportedType(rid); case Table.ManifestResource: return ResolveManifestResource(rid); case Table.GenericParam:return ResolveGenericParam(rid); case Table.MethodSpec: return ResolveMethodSpec(rid, gpContext); case Table.GenericParamConstraint: return ResolveGenericParamConstraint(rid, gpContext); } return null; } /// /// Resolves a /// /// A HasFieldMarshal coded token /// A or null if is invalid public IHasFieldMarshal ResolveHasFieldMarshal(uint codedToken) { uint token; if (!CodedToken.HasFieldMarshal.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.Field: return ResolveField(rid); case Table.Param: return ResolveParam(rid); } return null; } /// /// Resolves a /// /// A HasDeclSecurity coded token /// A or null if is invalid public IHasDeclSecurity ResolveHasDeclSecurity(uint codedToken) { uint token; if (!CodedToken.HasDeclSecurity.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.TypeDef: return ResolveTypeDef(rid); case Table.Method: return ResolveMethod(rid); case Table.Assembly: return ResolveAssembly(rid); } return null; } /// /// Resolves a /// /// A MemberRefParent coded token /// A or null if is invalid public IMemberRefParent ResolveMemberRefParent(uint codedToken) { return ResolveMemberRefParent(codedToken, new GenericParamContext()); } /// /// Resolves a /// /// A MemberRefParent coded token /// Generic parameter context /// A or null if is invalid public IMemberRefParent ResolveMemberRefParent(uint codedToken, GenericParamContext gpContext) { uint token; if (!CodedToken.MemberRefParent.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.TypeDef: return ResolveTypeDef(rid); case Table.TypeRef: return ResolveTypeRef(rid); case Table.ModuleRef: return ResolveModuleRef(rid); case Table.Method: return ResolveMethod(rid); case Table.TypeSpec: return ResolveTypeSpec(rid, gpContext); } return null; } /// /// Resolves a /// /// A HasSemantic coded token /// A or null if is invalid public IHasSemantic ResolveHasSemantic(uint codedToken) { uint token; if (!CodedToken.HasSemantic.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.Event: return ResolveEvent(rid); case Table.Property: return ResolveProperty(rid); } return null; } /// /// Resolves a /// /// A MethodDefOrRef coded token /// A or null if is invalid public IMethodDefOrRef ResolveMethodDefOrRef(uint codedToken) { return ResolveMethodDefOrRef(codedToken, new GenericParamContext()); } /// /// Resolves a /// /// A MethodDefOrRef coded token /// Generic parameter context /// A or null if is invalid public IMethodDefOrRef ResolveMethodDefOrRef(uint codedToken, GenericParamContext gpContext) { uint token; if (!CodedToken.MethodDefOrRef.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.Method: return ResolveMethod(rid); case Table.MemberRef: return ResolveMemberRef(rid, gpContext); } return null; } /// /// Resolves a /// /// A MemberForwarded coded token /// A or null if is invalid public IMemberForwarded ResolveMemberForwarded(uint codedToken) { uint token; if (!CodedToken.MemberForwarded.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.Field: return ResolveField(rid); case Table.Method: return ResolveMethod(rid); } return null; } /// /// Resolves an /// /// An Implementation coded token /// A or null if is invalid public IImplementation ResolveImplementation(uint codedToken) { uint token; if (!CodedToken.Implementation.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.File: return ResolveFile(rid); case Table.AssemblyRef: return ResolveAssemblyRef(rid); case Table.ExportedType: return ResolveExportedType(rid); } return null; } /// /// Resolves a /// /// A CustomAttributeType coded token /// A or null if is invalid public ICustomAttributeType ResolveCustomAttributeType(uint codedToken) { return ResolveCustomAttributeType(codedToken, new GenericParamContext()); } /// /// Resolves a /// /// A CustomAttributeType coded token /// Generic parameter context /// A or null if is invalid public ICustomAttributeType ResolveCustomAttributeType(uint codedToken, GenericParamContext gpContext) { uint token; if (!CodedToken.CustomAttributeType.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.Method: return ResolveMethod(rid); case Table.MemberRef: return ResolveMemberRef(rid, gpContext); } return null; } /// /// Resolves a /// /// A ResolutionScope coded token /// A or null if is invalid public IResolutionScope ResolveResolutionScope(uint codedToken) { uint token; if (!CodedToken.ResolutionScope.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.Module: return ResolveModule(rid); case Table.ModuleRef: return ResolveModuleRef(rid); case Table.AssemblyRef: return ResolveAssemblyRef(rid); case Table.TypeRef: return ResolveTypeRef(rid); } return null; } /// /// Resolves a /// /// A TypeOrMethodDef> coded token /// A or null if is invalid public ITypeOrMethodDef ResolveTypeOrMethodDef(uint codedToken) { uint token; if (!CodedToken.TypeOrMethodDef.Decode(codedToken, out token)) return null; uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.TypeDef: return ResolveTypeDef(rid); case Table.Method: return ResolveMethod(rid); } return null; } /// /// Reads a signature from the #Blob stream /// /// #Blob stream offset of signature /// A new instance or null if /// is invalid. public CallingConventionSig ReadSignature(uint sig) { return SignatureReader.ReadSig(this, sig, new GenericParamContext()); } /// /// Reads a signature from the #Blob stream /// /// #Blob stream offset of signature /// Generic parameter context /// A new instance or null if /// is invalid. public CallingConventionSig ReadSignature(uint sig, GenericParamContext gpContext) { return SignatureReader.ReadSig(this, sig, gpContext); } /// /// Reads a type signature from the #Blob stream /// /// #Blob stream offset of signature /// A new instance or null if /// is invalid. public TypeSig ReadTypeSignature(uint sig) { return SignatureReader.ReadTypeSig(this, sig, new GenericParamContext()); } /// /// Reads a type signature from the #Blob stream /// /// #Blob stream offset of signature /// Generic parameter context /// A new instance or null if /// is invalid. public TypeSig ReadTypeSignature(uint sig, GenericParamContext gpContext) { return SignatureReader.ReadTypeSig(this, sig, gpContext); } /// /// Reads a type signature from the #Blob stream /// /// #Blob stream offset of signature /// If there's any extra data after the signature, it's saved /// here, else this will be null /// A new instance or null if /// is invalid. public TypeSig ReadTypeSignature(uint sig, out byte[] extraData) { return SignatureReader.ReadTypeSig(this, sig, new GenericParamContext(), out extraData); } /// /// Reads a type signature from the #Blob stream /// /// #Blob stream offset of signature /// If there's any extra data after the signature, it's saved /// here, else this will be null /// Generic parameter context /// A new instance or null if /// is invalid. public TypeSig ReadTypeSignature(uint sig, GenericParamContext gpContext, out byte[] extraData) { return SignatureReader.ReadTypeSig(this, sig, gpContext, out extraData); } /// /// Reads a from the blob /// /// Table of owner /// Row ID of owner /// Generic parameter context /// A new instance or null if there's no field /// marshal for this owner. internal MarshalType ReadMarshalType(Table table, uint rid, GenericParamContext gpContext) { var row = TablesStream.ReadFieldMarshalRow(MetaData.GetFieldMarshalRid(table, rid)); if (row == null) return null; return MarshalBlobReader.Read(this, row.NativeType, gpContext); } /// /// Reads a CIL method body /// /// Method parameters /// RVA /// A new instance. It's empty if RVA is invalid (eg. 0 or /// it doesn't point to a CIL method body) public CilBody ReadCilBody(IList parameters, RVA rva) { return ReadCilBody(parameters, rva, new GenericParamContext()); } /// /// Reads a CIL method body /// /// Method parameters /// RVA /// Generic parameter context /// A new instance. It's empty if RVA is invalid (eg. 0 or /// it doesn't point to a CIL method body) public CilBody ReadCilBody(IList parameters, RVA rva, GenericParamContext gpContext) { if (rva == 0) return new CilBody(); // Create a full stream so position will be the real position in the file. This // is important when reading exception handlers since those must be 4-byte aligned. // If we create a partial stream starting from rva, then position will be 0 and always // 4-byte aligned. All fat method bodies should be 4-byte aligned, but the CLR doesn't // seem to verify it. We must parse the method exactly the way the CLR parses it. using (var reader = metaData.PEImage.CreateFullStream()) { reader.Position = (long)metaData.PEImage.ToFileOffset(rva); return MethodBodyReader.CreateCilBody(this, reader, parameters, gpContext); } } /// /// Returns the owner type of a field /// /// The field /// The owner type or null if none internal TypeDef GetOwnerType(FieldDefMD field) { return ResolveTypeDef(MetaData.GetOwnerTypeOfField(field.OrigRid)); } /// /// Returns the owner type of a method /// /// The method /// The owner type or null if none internal TypeDef GetOwnerType(MethodDefMD method) { return ResolveTypeDef(MetaData.GetOwnerTypeOfMethod(method.OrigRid)); } /// /// Returns the owner type of an event /// /// The event /// The owner type or null if none internal TypeDef GetOwnerType(EventDefMD evt) { return ResolveTypeDef(MetaData.GetOwnerTypeOfEvent(evt.OrigRid)); } /// /// Returns the owner type of a property /// /// The property /// The owner type or null if none internal TypeDef GetOwnerType(PropertyDefMD property) { return ResolveTypeDef(MetaData.GetOwnerTypeOfProperty(property.OrigRid)); } /// /// Returns the owner type/method of a generic param /// /// The generic param /// The owner type/method or null if none internal ITypeOrMethodDef GetOwner(GenericParamMD gp) { return ResolveTypeOrMethodDef(MetaData.GetOwnerOfGenericParam(gp.OrigRid)); } /// /// Returns the owner generic param of a generic param constraint /// /// The generic param constraint /// The owner generic param or null if none internal GenericParam GetOwner(GenericParamConstraintMD gpc) { return ResolveGenericParam(MetaData.GetOwnerOfGenericParamConstraint(gpc.OrigRid)); } /// /// Returns the owner method of a param /// /// The param /// The owner method or null if none internal MethodDef GetOwner(ParamDefMD pd) { return ResolveMethod(MetaData.GetOwnerOfParam(pd.OrigRid)); } /// /// Reads a module /// /// File rid /// The assembly owning the module we should read /// A new instance or null if /// is invalid or if it's not a .NET module. internal ModuleDefMD ReadModule(uint fileRid, AssemblyDef owner) { var fileDef = ResolveFile(fileRid); if (fileDef == null) return null; if (!fileDef.ContainsMetaData) return null; var fileName = GetValidFilename(GetBaseDirectoryOfImage(), UTF8String.ToSystemString(fileDef.Name)); if (fileName == null) return null; ModuleDefMD module; try { module = ModuleDefMD.Load(fileName); } catch { module = null; } if (module != null) { // share context module.context = context; var asm = module.Assembly; if (asm != null && asm != owner) asm.Modules.Remove(module); } return module; } /// /// Gets a list of all File rids that are .NET modules. Call /// to read one of these modules. /// /// A new instance internal RidList GetModuleRidList() { if (moduleRidList == null) InitializeModuleList(); return moduleRidList; } void InitializeModuleList() { if (moduleRidList != null) return; uint rows = TablesStream.FileTable.Rows; var newModuleRidList = new RandomRidList((int)rows); var baseDir = GetBaseDirectoryOfImage(); for (uint fileRid = 1; fileRid <= rows; fileRid++) { var fileDef = ResolveFile(fileRid); if (fileDef == null) continue; // Should never happen if (!fileDef.ContainsMetaData) continue; var pathName = GetValidFilename(baseDir, UTF8String.ToSystemString(fileDef.Name)); if (pathName != null) newModuleRidList.Add(fileRid); } Interlocked.CompareExchange(ref moduleRidList, newModuleRidList, null); } /// /// Concatenates the inputs and returns the result if it's a valid path /// /// Base dir /// File name /// Full path to the file or null if one of the inputs is invalid static string GetValidFilename(string baseDir, string name) { if (baseDir == null) return null; string pathName; try { if (name.IndexOfAny(Path.GetInvalidPathChars()) >= 0) return null; pathName = Path.Combine(baseDir, name); if (pathName != Path.GetFullPath(pathName)) return null; if (!File.Exists(pathName)) return null; } catch { return null; } return pathName; } /// /// Gets the base directory where this .NET module is located on disk /// /// Base directory or null if unknown or if an error occurred string GetBaseDirectoryOfImage() { var imageFileName = Location; if (string.IsNullOrEmpty(imageFileName)) return null; try { return Path.GetDirectoryName(imageFileName); } catch (IOException) { } catch (ArgumentException) { } return null; } /// /// Creates a instance /// /// ManifestResource rid /// A new instance Resource CreateResource(uint rid) { var row = TablesStream.ReadManifestResourceRow(rid); if (row == null) return new EmbeddedResource(UTF8String.Empty, MemoryImageStream.CreateEmpty(), 0) { Rid = rid }; MDToken token; if (!CodedToken.Implementation.Decode(row.Implementation, out token)) return new EmbeddedResource(UTF8String.Empty, MemoryImageStream.CreateEmpty(), 0) { Rid = rid }; var mr = ResolveManifestResource(rid); if (mr == null) return new EmbeddedResource(UTF8String.Empty, MemoryImageStream.CreateEmpty(), 0) { Rid = rid }; if (token.Rid == 0) return new EmbeddedResource(mr.Name, CreateResourceStream(mr.Offset), mr.Flags) { Rid = rid, Offset = mr.Offset }; var file = mr.Implementation as FileDef; if (file != null) return new LinkedResource(mr.Name, file, mr.Flags) { Rid = rid, Offset = mr.Offset }; var asmRef = mr.Implementation as AssemblyRef; if (asmRef != null) return new AssemblyLinkedResource(mr.Name, asmRef, mr.Flags) { Rid = rid, Offset = mr.Offset }; return new EmbeddedResource(mr.Name, MemoryImageStream.CreateEmpty(), mr.Flags) { Rid = rid, Offset = mr.Offset }; } /// /// Creates a resource stream that can access part of the resource section of this module /// /// Offset of resource relative to the .NET resources section /// A stream the size of the resource [HandleProcessCorruptedStateExceptions, SecurityCritical] // Req'd on .NET 4.0 IImageStream CreateResourceStream(uint offset) { IImageStream fs = null, imageStream = null; try { var peImage = metaData.PEImage; var cor20Header = metaData.ImageCor20Header; var resources = cor20Header.Resources; if (resources.VirtualAddress == 0 || resources.Size == 0) return MemoryImageStream.CreateEmpty(); fs = peImage.CreateFullStream(); var resourceOffset = (long)peImage.ToFileOffset(resources.VirtualAddress); if (resourceOffset <= 0 || resourceOffset + offset < resourceOffset) return MemoryImageStream.CreateEmpty(); if (offset + 3 <= offset || offset + 3 >= resources.Size) return MemoryImageStream.CreateEmpty(); if (resourceOffset + offset + 3 < resourceOffset || resourceOffset + offset + 3 >= fs.Length) return MemoryImageStream.CreateEmpty(); fs.Position = resourceOffset + offset; uint length = fs.ReadUInt32(); // Could throw if (length == 0 || fs.Position + length - 1 < fs.Position || fs.Position + length - 1 >= fs.Length) return MemoryImageStream.CreateEmpty(); if (fs.Position - resourceOffset + length - 1 >= resources.Size) return MemoryImageStream.CreateEmpty(); imageStream = peImage.CreateStream((FileOffset)fs.Position, length); if (peImage.MayHaveInvalidAddresses) { for (; imageStream.Position < imageStream.Length; imageStream.Position += 0x1000) imageStream.ReadByte(); // Could throw imageStream.Position = imageStream.Length - 1; // length is never 0 if we're here imageStream.ReadByte(); // Could throw imageStream.Position = 0; } } catch (AccessViolationException) { if (imageStream != null) imageStream.Dispose(); return MemoryImageStream.CreateEmpty(); } finally { if (fs != null) fs.Dispose(); } return imageStream; } /// /// Reads a /// /// Custom attribute rid /// A new instance or null if /// is invalid public CustomAttribute ReadCustomAttribute(uint caRid) { return ReadCustomAttribute(caRid, new GenericParamContext()); } /// /// Reads a /// /// Custom attribute rid /// Generic parameter context /// A new instance or null if /// is invalid public CustomAttribute ReadCustomAttribute(uint caRid, GenericParamContext gpContext) { var caRow = TablesStream.ReadCustomAttributeRow(caRid); if (caRow == null) return null; return CustomAttributeReader.Read(this, ResolveCustomAttributeType(caRow.Type, gpContext), caRow.Value, gpContext); } /// /// Reads data somewhere in the address space of the image /// /// RVA of data /// Size of data /// All the data or null if or /// is invalid public byte[] ReadDataAt(RVA rva, int size) { if (size < 0) return null; var peImage = MetaData.PEImage; using (var reader = peImage.CreateStream(rva, size)) { if (reader.Length < size) return null; return reader.ReadBytes(size); } } /// /// Gets the native entry point or 0 if none /// public RVA GetNativeEntryPoint() { var cor20Header = MetaData.ImageCor20Header; if ((cor20Header.Flags & ComImageFlags.NativeEntryPoint) == 0) return 0; return (RVA)cor20Header.EntryPointToken_or_RVA; } /// /// Gets the managed entry point (a Method or a File) or null if none /// public IManagedEntryPoint GetManagedEntryPoint() { var cor20Header = MetaData.ImageCor20Header; if ((cor20Header.Flags & ComImageFlags.NativeEntryPoint) != 0) return null; return ResolveToken(cor20Header.EntryPointToken_or_RVA) as IManagedEntryPoint; } /// /// Reads a new instance. This one is not cached. /// /// Row ID /// A new instance internal FieldDefMD ReadField(uint rid) { return new FieldDefMD(this, rid); } /// /// Reads a new instance. This one is not cached. /// /// Row ID /// A new instance internal MethodDefMD ReadMethod(uint rid) { return new MethodDefMD(this, rid); } /// /// Reads a new instance. This one is not cached. /// /// Row ID /// A new instance internal EventDefMD ReadEvent(uint rid) { return new EventDefMD(this, rid); } /// /// Reads a new instance. This one is not cached. /// /// Row ID /// A new instance internal PropertyDefMD ReadProperty(uint rid) { return new PropertyDefMD(this, rid); } /// /// Reads a new instance. This one is not cached. /// /// Row ID /// A new instance internal ParamDefMD ReadParam(uint rid) { return new ParamDefMD(this, rid); } /// /// Reads a new instance. This one is not cached. /// /// Row ID /// A new instance internal GenericParamMD ReadGenericParam(uint rid) { return new GenericParamMD(this, rid); } /// /// Reads a new instance. This one is not cached. /// /// Row ID /// A new instance internal GenericParamConstraintMD ReadGenericParamConstraint(uint rid) { return new GenericParamConstraintMD(this, rid, new GenericParamContext()); } /// /// Reads a new instance. This one is not cached. /// /// Row ID /// Generic parameter context /// A new instance internal GenericParamConstraintMD ReadGenericParamConstraint(uint rid, GenericParamContext gpContext) { return new GenericParamConstraintMD(this, rid, gpContext); } /// /// Reads a method body /// /// Method /// Method RVA /// Method impl attrs /// Generic parameter context /// A or null if none internal MethodBody ReadMethodBody(MethodDefMD method, RVA rva, MethodImplAttributes implAttrs, GenericParamContext gpContext) { MethodBody mb; var mDec = methodDecrypter; if (mDec != null && mDec.GetMethodBody(method.OrigRid, rva, method.Parameters, gpContext, out mb)) { var cilBody = mb as CilBody; if (cilBody != null) return InitializeBodyFromPdb(method, cilBody); return mb; } if (rva == 0) return null; var codeType = implAttrs & MethodImplAttributes.CodeTypeMask; if (codeType == MethodImplAttributes.IL) return InitializeBodyFromPdb(method, ReadCilBody(method.Parameters, rva, gpContext)); if (codeType == MethodImplAttributes.Native) return new NativeMethodBody(rva); return null; } /// /// Updates with the PDB info (if any) /// /// Owner method /// Method body /// Returns originak value CilBody InitializeBodyFromPdb(MethodDefMD method, CilBody body) { var ps = pdbState; if (ps != null) ps.InitializeMethodBody(this, method, body); return body; } internal void InitializeCustomDebugInfos(MethodDefMD method, CilBody body, IList customDebugInfos) { if (body == null) return; var ps = pdbState; if (ps != null) ps.InitializeCustomDebugInfos(method, body, customDebugInfos); } /// /// Reads a string from the #US heap /// /// String token /// A non-null string public string ReadUserString(uint token) { var sDec = stringDecrypter; if (sDec != null) { var s = sDec.ReadUserString(token); if (s != null) return s; } return USStream.ReadNoNull(token & 0x00FFFFFF); } internal MethodExportInfo GetExportInfo(uint methodRid) { if (methodExportInfoProvider == null) InitializeMethodExportInfoProvider(); return methodExportInfoProvider.GetMethodExportInfo(0x06000000 + methodRid); } void InitializeMethodExportInfoProvider() { Interlocked.CompareExchange(ref methodExportInfoProvider, new MethodExportInfoProvider(this), null); } MethodExportInfoProvider methodExportInfoProvider; /// /// Writes the mixed-mode module to a file on disk. If the file exists, it will be overwritten. /// /// Filename public void NativeWrite(string filename) { NativeWrite(filename, null); } /// /// Writes the mixed-mode module to a file on disk. If the file exists, it will be overwritten. /// /// Filename /// Writer options public void NativeWrite(string filename, DNW.NativeModuleWriterOptions options) { var writer = new DNW.NativeModuleWriter(this, options ?? new DNW.NativeModuleWriterOptions(this)); writer.Write(filename); } /// /// Writes the mixed-mode module to a stream. /// /// Destination stream public void NativeWrite(Stream dest) { NativeWrite(dest, null); } /// /// Writes the mixed-mode module to a stream. /// /// Destination stream /// Writer options public void NativeWrite(Stream dest, DNW.NativeModuleWriterOptions options) { var writer = new DNW.NativeModuleWriter(this, options ?? new DNW.NativeModuleWriterOptions(this)); writer.Write(dest); } /// /// Reads data from the #Blob. The following columns are returned: /// Field.Signature /// Method.Signature /// MemberRef.Signature /// Constant.Value /// CustomAttribute.Value /// FieldMarshal.NativeType /// DeclSecurity.PermissionSet /// StandAloneSig.Signature /// Property.Type /// TypeSpec.Signature /// Assembly.PublicKey /// AssemblyRef.PublicKeyOrToken /// File.HashValue /// MethodSpec.Instantiation /// /// A token /// The value in the #Blob or null if is invalid public byte[] ReadBlob(uint token) { uint rid = MDToken.ToRID(token); switch (MDToken.ToTable(token)) { case Table.Field: var fieldRow = TablesStream.ReadFieldRow(rid); if (fieldRow == null) break; return BlobStream.Read(fieldRow.Signature); case Table.Method: var methodRow = TablesStream.ReadMethodRow(rid); if (methodRow == null) break; return BlobStream.Read(methodRow.Signature); case Table.MemberRef: var mrRow = TablesStream.ReadMemberRefRow(rid); if (mrRow == null) break; return BlobStream.Read(mrRow.Signature); case Table.Constant: var constRow = TablesStream.ReadConstantRow(rid); if (constRow == null) break; return BlobStream.Read(constRow.Value); case Table.CustomAttribute: var caRow = TablesStream.ReadCustomAttributeRow(rid); if (caRow == null) break; return BlobStream.Read(caRow.Value); case Table.FieldMarshal: var fmRow = TablesStream.ReadFieldMarshalRow(rid); if (fmRow == null) break; return BlobStream.Read(fmRow.NativeType); case Table.DeclSecurity: var dsRow = TablesStream.ReadDeclSecurityRow(rid); if (dsRow == null) break; return BlobStream.Read(dsRow.PermissionSet); case Table.StandAloneSig: var sasRow = TablesStream.ReadStandAloneSigRow(rid); if (sasRow == null) break; return BlobStream.Read(sasRow.Signature); case Table.Property: var propRow = TablesStream.ReadPropertyRow(rid); if (propRow == null) break; return BlobStream.Read(propRow.Type); case Table.TypeSpec: var tsRow = TablesStream.ReadTypeSpecRow(rid); if (tsRow == null) break; return BlobStream.Read(tsRow.Signature); case Table.Assembly: var asmRow = TablesStream.ReadAssemblyRow(rid); if (asmRow == null) break; return BlobStream.Read(asmRow.PublicKey); case Table.AssemblyRef: // HashValue is also in the #Blob but the user has to read it some other way var asmRefRow = TablesStream.ReadAssemblyRefRow(rid); if (asmRefRow == null) break; return BlobStream.Read(asmRefRow.PublicKeyOrToken); case Table.File: var fileRow = TablesStream.ReadFileRow(rid); if (fileRow == null) break; return BlobStream.Read(fileRow.HashValue); case Table.MethodSpec: var msRow = TablesStream.ReadMethodSpecRow(rid); if (msRow == null) break; return BlobStream.Read(msRow.Instantiation); } return null; } } } dnlib-2.1_VS2010/src/DotNet/ModuleKind.cs000066400000000000000000000006651325033663500177420ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Module kind /// public enum ModuleKind { /// /// Console UI module /// Console, /// /// Windows GUI module /// Windows, /// /// DLL module /// Dll, /// /// Netmodule (it has no assembly manifest) /// NetModule, } } dnlib-2.1_VS2010/src/DotNet/ModuleLoader.cs000066400000000000000000000473211325033663500202630ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using dnlib.DotNet.Emit; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.IO; using dnlib.PE; using dnlib.Threading; using dnlib.W32Resources; namespace dnlib.DotNet { struct ModuleLoader { readonly ModuleDef module; readonly ICancellationToken cancellationToken; readonly Dictionary seen; readonly Stack stack; ModuleLoader(ModuleDef module, ICancellationToken cancellationToken) { const int CAPACITY = 0x4000; this.module = module; this.cancellationToken = cancellationToken; this.seen = new Dictionary(CAPACITY); this.stack = new Stack(CAPACITY); } public static void LoadAll(ModuleDef module, ICancellationToken cancellationToken) { new ModuleLoader(module, cancellationToken).Load(); } void Add(UTF8String a) { } void Add(Guid? a) { } void Add(ushort a) { } void Add(AssemblyHashAlgorithm a) { } void Add(Version a) { } void Add(AssemblyAttributes a) { } void Add(PublicKeyBase a) { } void Add(RVA a) { } void Add(IManagedEntryPoint a) { } void Add(string a) { } void Add(WinMDStatus a) { } void Add(TypeAttributes a) { } void Add(FieldAttributes a) { } void Add(uint? a) { } void Add(byte[] a) { } void Add(MethodImplAttributes a) { } void Add(MethodAttributes a) { } void Add(MethodSemanticsAttributes a) { } void Add(ParamAttributes a) { } void Add(ElementType a) { } void Add(SecurityAction a) { } void Add(EventAttributes a) { } void Add(PropertyAttributes a) { } void Add(PInvokeAttributes a) { } void Add(FileAttributes a) { } void Add(ManifestResourceAttributes a) { } void Add(GenericParamAttributes a) { } void Add(NativeType a) { } void Load() { LoadAllTables(); Load(module); Process(); } void Process() { while (stack.Count != 0) { if (cancellationToken != null) cancellationToken.ThrowIfCancellationRequested(); var o = stack.Pop(); LoadObj(o); } } void LoadAllTables() { var resolver = module as ITokenResolver; if (resolver == null) return; for (Table tbl = 0; tbl <= Table.GenericParamConstraint; tbl++) { for (uint rid = 1; ; rid++) { var o = resolver.ResolveToken(new MDToken(tbl, rid).Raw, new GenericParamContext()); if (o == null) break; Add(o); Process(); } } } void LoadObj(object o) { var ts = o as TypeSig; if (ts != null) { Load(ts); return; } var mdt = o as IMDTokenProvider; if (mdt != null) { Load(mdt); return; } var ca = o as CustomAttribute; if (ca != null) { Load(ca); return; } var sa = o as SecurityAttribute; if (sa != null) { Load(sa); return; } var na = o as CANamedArgument; if (na != null) { Load(na); return; } var p = o as Parameter; if (p != null) { Load(p); return; } var pdbMethod = o as PdbMethod; if (pdbMethod != null) { Load(pdbMethod); return; } var rd = o as ResourceDirectory; if (rd != null) { Load(rd); return; } var rdata = o as ResourceData; if (rdata != null) { Load(rdata); return; } Debug.Fail("Unknown type"); } void Load(TypeSig ts) { if (ts == null) return; Add(ts.Next); switch (ts.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.ValueType: case ElementType.Class: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: Add(((TypeDefOrRefSig)ts).TypeDefOrRef); break; case ElementType.Var: case ElementType.MVar: var vsig = (GenericSig)ts; Add(vsig.OwnerType); Add(vsig.OwnerMethod); break; case ElementType.GenericInst: var gis = (GenericInstSig)ts; Add(gis.GenericType); Add(gis.GenericArguments); break; case ElementType.FnPtr: var fpsig = (FnPtrSig)ts; Add(fpsig.Signature); break; case ElementType.CModReqd: case ElementType.CModOpt: var cmod = (ModifierSig)ts; Add(cmod.Modifier); break; case ElementType.End: case ElementType.Ptr: case ElementType.ByRef: case ElementType.Array: case ElementType.ValueArray: case ElementType.SZArray: case ElementType.Module: case ElementType.Pinned: case ElementType.Sentinel: case ElementType.R: case ElementType.Internal: default: break; } } void Load(IMDTokenProvider mdt) { if (mdt == null) return; switch (mdt.MDToken.Table) { case Table.Module: Load((ModuleDef)mdt); break; case Table.TypeRef: Load((TypeRef)mdt); break; case Table.TypeDef: Load((TypeDef)mdt); break; case Table.Field: Load((FieldDef)mdt); break; case Table.Method: Load((MethodDef)mdt); break; case Table.Param: Load((ParamDef)mdt); break; case Table.InterfaceImpl: Load((InterfaceImpl)mdt); break; case Table.MemberRef: Load((MemberRef)mdt); break; case Table.Constant: Load((Constant)mdt); break; case Table.DeclSecurity: Load((DeclSecurity)mdt); break; case Table.ClassLayout: Load((ClassLayout)mdt); break; case Table.StandAloneSig: Load((StandAloneSig)mdt); break; case Table.Event: Load((EventDef)mdt); break; case Table.Property: Load((PropertyDef)mdt); break; case Table.ModuleRef: Load((ModuleRef)mdt); break; case Table.TypeSpec: Load((TypeSpec)mdt); break; case Table.ImplMap: Load((ImplMap)mdt); break; case Table.Assembly: Load((AssemblyDef)mdt); break; case Table.AssemblyRef: Load((AssemblyRef)mdt); break; case Table.File: Load((FileDef)mdt); break; case Table.ExportedType: Load((ExportedType)mdt); break; case Table.GenericParam: Load((GenericParam)mdt); break; case Table.MethodSpec: Load((MethodSpec)mdt); break; case Table.GenericParamConstraint: Load((GenericParamConstraint)mdt); break; case Table.ManifestResource: var rsrc = mdt as Resource; if (rsrc != null) { Load(rsrc); break; } var mr = mdt as ManifestResource; if (mr != null) { Load(mr); break; } Debug.Fail("Unknown ManifestResource"); break; case Table.FieldPtr: case Table.MethodPtr: case Table.ParamPtr: case Table.CustomAttribute: case Table.FieldMarshal: case Table.FieldLayout: case Table.EventMap: case Table.EventPtr: case Table.PropertyMap: case Table.PropertyPtr: case Table.MethodSemantics: case Table.MethodImpl: case Table.FieldRVA: case Table.ENCLog: case Table.ENCMap: case Table.AssemblyProcessor: case Table.AssemblyOS: case Table.AssemblyRefProcessor: case Table.AssemblyRefOS: case Table.NestedClass: case Table.Document: case Table.MethodDebugInformation: case Table.LocalScope: case Table.LocalVariable: case Table.LocalConstant: case Table.ImportScope: case Table.StateMachineMethod: case Table.CustomDebugInformation: break; default: Debug.Fail("Unknown type"); break; } } void Load(ModuleDef obj) { if (obj == null || obj != this.module) return; Add(obj.Generation); Add(obj.Name); Add(obj.Mvid); Add(obj.EncId); Add(obj.EncBaseId); Add(obj.CustomAttributes); Add(obj.Assembly); Add(obj.Types); Add(obj.ExportedTypes); Add(obj.NativeEntryPoint); Add(obj.ManagedEntryPoint); Add(obj.Resources); Add(obj.VTableFixups); Add(obj.Location); Add(obj.Win32Resources); Add(obj.RuntimeVersion); Add(obj.WinMDStatus); Add(obj.RuntimeVersionWinMD); Add(obj.WinMDVersion); Add(obj.PdbState); } void Load(TypeRef obj) { if (obj == null) return; Add(obj.ResolutionScope); Add(obj.Name); Add(obj.Namespace); Add(obj.CustomAttributes); } void Load(TypeDef obj) { if (obj == null) return; Add(obj.Module2); Add(obj.Attributes); Add(obj.Name); Add(obj.Namespace); Add(obj.BaseType); Add(obj.Fields); Add(obj.Methods); Add(obj.GenericParameters); Add(obj.Interfaces); Add(obj.DeclSecurities); Add(obj.ClassLayout); Add(obj.DeclaringType); Add(obj.DeclaringType2); Add(obj.NestedTypes); Add(obj.Events); Add(obj.Properties); Add(obj.CustomAttributes); } void Load(FieldDef obj) { if (obj == null) return; Add(obj.CustomAttributes); Add(obj.Attributes); Add(obj.Name); Add(obj.Signature); Add(obj.FieldOffset); Add(obj.MarshalType); Add(obj.RVA); Add(obj.InitialValue); Add(obj.ImplMap); Add(obj.Constant); Add(obj.DeclaringType); } void Load(MethodDef obj) { if (obj == null) return; Add(obj.RVA); Add(obj.ImplAttributes); Add(obj.Attributes); Add(obj.Name); Add(obj.Signature); Add(obj.ParamDefs); Add(obj.GenericParameters); Add(obj.DeclSecurities); Add(obj.ImplMap); Add(obj.MethodBody); Add(obj.CustomAttributes); Add(obj.Overrides); Add(obj.DeclaringType); Add(obj.Parameters); Add(obj.SemanticsAttributes); } void Load(ParamDef obj) { if (obj == null) return; Add(obj.DeclaringMethod); Add(obj.Attributes); Add(obj.Sequence); Add(obj.Name); Add(obj.MarshalType); Add(obj.Constant); Add(obj.CustomAttributes); } void Load(InterfaceImpl obj) { if (obj == null) return; Add(obj.Interface); Add(obj.CustomAttributes); } void Load(MemberRef obj) { if (obj == null) return; Add(obj.Class); Add(obj.Name); Add(obj.Signature); Add(obj.CustomAttributes); } void Load(Constant obj) { if (obj == null) return; Add(obj.Type); var o = obj.Value; } void Load(DeclSecurity obj) { if (obj == null) return; Add(obj.Action); Add(obj.SecurityAttributes); Add(obj.CustomAttributes); obj.GetBlob(); } void Load(ClassLayout obj) { if (obj == null) return; Add(obj.PackingSize); Add(obj.ClassSize); } void Load(StandAloneSig obj) { if (obj == null) return; Add(obj.Signature); Add(obj.CustomAttributes); } void Load(EventDef obj) { if (obj == null) return; Add(obj.Attributes); Add(obj.Name); Add(obj.EventType); Add(obj.CustomAttributes); Add(obj.AddMethod); Add(obj.InvokeMethod); Add(obj.RemoveMethod); Add(obj.OtherMethods); Add(obj.DeclaringType); } void Load(PropertyDef obj) { if (obj == null) return; Add(obj.Attributes); Add(obj.Name); Add(obj.Type); Add(obj.Constant); Add(obj.CustomAttributes); Add(obj.GetMethods); Add(obj.SetMethods); Add(obj.OtherMethods); Add(obj.DeclaringType); } void Load(ModuleRef obj) { if (obj == null) return; Add(obj.Name); Add(obj.CustomAttributes); } void Load(TypeSpec obj) { if (obj == null) return; Add(obj.TypeSig); Add(obj.ExtraData); Add(obj.CustomAttributes); } void Load(ImplMap obj) { if (obj == null) return; Add(obj.Attributes); Add(obj.Name); Add(obj.Module); } void Load(AssemblyDef obj) { if (obj == null) return; if (obj.ManifestModule != module) return; Add(obj.HashAlgorithm); Add(obj.Version); Add(obj.Attributes); Add(obj.PublicKey); Add(obj.Name); Add(obj.Culture); Add(obj.DeclSecurities); Add(obj.Modules); Add(obj.CustomAttributes); } void Load(AssemblyRef obj) { if (obj == null) return; Add(obj.Version); Add(obj.Attributes); Add(obj.PublicKeyOrToken); Add(obj.Name); Add(obj.Culture); Add(obj.Hash); Add(obj.CustomAttributes); } void Load(FileDef obj) { if (obj == null) return; Add(obj.Flags); Add(obj.Name); Add(obj.HashValue); Add(obj.CustomAttributes); } void Load(ExportedType obj) { if (obj == null) return; Add(obj.CustomAttributes); Add(obj.Attributes); Add(obj.TypeDefId); Add(obj.TypeName); Add(obj.TypeNamespace); Add(obj.Implementation); } void Load(Resource obj) { if (obj == null) return; Add(obj.Offset); Add(obj.Name); Add(obj.Attributes); switch (obj.ResourceType) { case ResourceType.Embedded: var er = (EmbeddedResource)obj; // Make sure data is cached if (!(er.Data is MemoryImageStream)) er.Data = MemoryImageStream.Create(er.GetClonedResourceStream().ReadAllBytes()); break; case ResourceType.AssemblyLinked: var ar = (AssemblyLinkedResource)obj; Add(ar.Assembly); break; case ResourceType.Linked: var lr = (LinkedResource)obj; Add(lr.File); Add(lr.Hash); break; default: Debug.Fail("Unknown resource"); break; } } void Load(ManifestResource obj) { if (obj == null) return; Add(obj.Offset); Add(obj.Flags); Add(obj.Name); Add(obj.Implementation); Add(obj.CustomAttributes); } void Load(GenericParam obj) { if (obj == null) return; Add(obj.Owner); Add(obj.Number); Add(obj.Flags); Add(obj.Name); Add(obj.Kind); Add(obj.GenericParamConstraints); Add(obj.CustomAttributes); } void Load(MethodSpec obj) { if (obj == null) return; Add(obj.Method); Add(obj.Instantiation); Add(obj.CustomAttributes); } void Load(GenericParamConstraint obj) { if (obj == null) return; Add(obj.Owner); Add(obj.Constraint); Add(obj.CustomAttributes); } void Load(CANamedArgument obj) { if (obj == null) return; Add(obj.Type); Add(obj.Name); Load(obj.Argument); } void Load(Parameter obj) { if (obj == null) return; Add(obj.Type); } void Load(SecurityAttribute obj) { if (obj == null) return; Add(obj.AttributeType); Add(obj.NamedArguments); } void Load(CustomAttribute obj) { if (obj == null) return; Add(obj.Constructor); Add(obj.RawData); Add(obj.ConstructorArguments); Add(obj.NamedArguments); } void Load(MethodOverride obj) { Add(obj.MethodBody); Add(obj.MethodDeclaration); } void AddCAValue(object obj) { if (obj is CAArgument) { Load((CAArgument)obj); return; } var list = obj as IList; if (list != null) { Add(list); return; } var md = obj as IMDTokenProvider; if (md != null) { Add(md); return; } } void Load(CAArgument obj) { Add(obj.Type); AddCAValue(obj.Value); } void Load(PdbMethod obj) { } void Load(ResourceDirectory obj) { if (obj == null) return; Add(obj.Directories); Add(obj.Data); } void Load(ResourceData obj) { if (obj == null) return; var data = obj.Data; if (data != null && !(data is MemoryImageStream)) obj.Data = MemoryImageStream.Create(data.ReadAllBytes()); } void AddToStack(T t) where T : class { if (t == null) return; if (seen.ContainsKey(t)) return; seen[t] = true; stack.Push(t); } void Add(CustomAttribute obj) { AddToStack(obj); } void Add(SecurityAttribute obj) { AddToStack(obj); } void Add(CANamedArgument obj) { AddToStack(obj); } void Add(Parameter obj) { AddToStack(obj); } void Add(IMDTokenProvider o) { AddToStack(o); } void Add(PdbMethod pdbMethod) { } void Add(TypeSig ts) { AddToStack(ts); } void Add(ResourceDirectory rd) { AddToStack(rd); } void Add(ResourceData rd) { AddToStack(rd); } void Add(IList list) where T : IMDTokenProvider { if (list == null) return; foreach (var item in list.GetSafeEnumerable()) Add(item); } void Add(IList list) { if (list == null) return; foreach (var item in list.GetSafeEnumerable()) Add(item); } void Add(IList list) { if (list == null) return; foreach (var item in list.GetSafeEnumerable()) Add(item); } void Add(IList list) { if (list == null) return; foreach (var item in list.GetSafeEnumerable()) Add(item); } void Add(IList list) { if (list == null) return; foreach (var item in list.GetSafeEnumerable()) Load(item); } void Add(IList list) { if (list == null) return; foreach (var item in list.GetSafeEnumerable()) Load(item); } void Add(IList list) { if (list == null) return; foreach (var item in list.GetSafeEnumerable()) Add(item); } void Add(ParameterList list) { if (list == null) return; foreach (var item in list.GetSafeEnumerable()) Add(item); } void Add(IList list) { if (list == null) return; foreach (var item in list.GetSafeEnumerable()) Add(item); } void Add(IList list) { if (list == null) return; foreach (var item in list.GetSafeEnumerable()) Add(item); } void Add(IList list) { if (list == null) return; foreach (var item in list.GetSafeEnumerable()) Add(item); } void Add(IList list) { if (list == null) return; foreach (var item in list.GetSafeEnumerable()) Add(item); } void Add(IList list) { if (list == null) return; foreach (var item in list.GetSafeEnumerable()) Add(item); } void Add(VTableFixups vtf) { if (vtf == null) return; foreach (var fixup in vtf) { foreach (var method in fixup) Add(method); } } void Add(Win32Resources vtf) { if (vtf == null) return; Add(vtf.Root); } void Add(CallingConventionSig sig) { var msig = sig as MethodBaseSig; if (msig != null) { Add(msig); return; } var fsig = sig as FieldSig; if (fsig != null) { Add(fsig); return; } var lsig = sig as LocalSig; if (lsig != null) { Add(lsig); return; } var gsig = sig as GenericInstMethodSig; if (gsig != null) { Add(gsig); return; } Debug.Assert(sig == null); } void Add(MethodBaseSig msig) { if (msig == null) return; Add(msig.ExtraData); Add(msig.RetType); Add(msig.Params); Add(msig.ParamsAfterSentinel); } void Add(FieldSig fsig) { if (fsig == null) return; Add(fsig.ExtraData); Add(fsig.Type); } void Add(LocalSig lsig) { if (lsig == null) return; Add(lsig.ExtraData); Add(lsig.Locals); } void Add(GenericInstMethodSig gsig) { if (gsig == null) return; Add(gsig.ExtraData); Add(gsig.GenericArguments); } void Add(MarshalType mt) { if (mt == null) return; Add(mt.NativeType); } void Add(MethodBody mb) { var cilBody = mb as CilBody; if (cilBody != null) { Add(cilBody); return; } var nb = mb as NativeMethodBody; if (nb != null) { Add(nb); return; } Debug.Assert(mb == null, "Unknown method body"); } void Add(NativeMethodBody body) { if (body == null) return; Add(body.RVA); } void Add(CilBody body) { if (body == null) return; Add(body.Instructions); Add(body.ExceptionHandlers); Add(body.Variables); Add(body.PdbMethod); } void Add(Instruction instr) { if (instr == null) return; var mdt = instr.Operand as IMDTokenProvider; if (mdt != null) { Add(mdt); return; } var p = instr.Operand as Parameter; if (p != null) { Add(p); return; } var l = instr.Operand as Local; if (l != null) { Add(l); return; } var csig = instr.Operand as CallingConventionSig; if (csig != null) { Add(csig); return; } } void Add(ExceptionHandler eh) { if (eh == null) return; Add(eh.CatchType); } void Add(Local local) { if (local == null) return; Add(local.Type); } void Add(PdbState state) { if (state == null) return; Add(state.UserEntryPoint); } } } dnlib-2.1_VS2010/src/DotNet/ModuleRef.cs000066400000000000000000000146051325033663500175700ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the ModuleRef table /// public abstract class ModuleRef : IHasCustomAttribute, IMemberRefParent, IHasCustomDebugInformation, IResolutionScope, IModule, IOwnerModule { /// /// The row id in its table /// protected uint rid; /// /// The owner module /// protected ModuleDef module; /// public MDToken MDToken { get { return new MDToken(Table.ModuleRef, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 12; } } /// public int MemberRefParentTag { get { return 2; } } /// public int ResolutionScopeTag { get { return 1; } } /// public ScopeType ScopeType { get { return ScopeType.ModuleRef; } } /// public string ScopeName { get { return FullName; } } /// /// From column ModuleRef.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 12; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// public ModuleDef Module { get { return module; } } /// /// Gets the definition module, i.e., the module which it references, or null /// if the module can't be found. /// public ModuleDef DefinitionModule { get { if (module == null) return null; var n = name; if (UTF8String.CaseInsensitiveEquals(n, module.Name)) return module; var asm = DefinitionAssembly; return asm == null ? null : asm.FindModule(n); } } /// /// Gets the definition assembly, i.e., the assembly of the module it references, or /// null if the assembly can't be found. /// public AssemblyDef DefinitionAssembly { get { return module == null ? null : module.Assembly; } } /// public string FullName { get { return UTF8String.ToSystemStringOrEmpty(name); } } /// public override string ToString() { return FullName; } } /// /// A ModuleRef row created by the user and not present in the original .NET file /// public class ModuleRefUser : ModuleRef { /// /// Constructor /// /// Owner module public ModuleRefUser(ModuleDef module) : this(module, UTF8String.Empty) { } /// /// Constructor /// /// Owner module /// Module name public ModuleRefUser(ModuleDef module, UTF8String name) { this.module = module; this.name = name; } } /// /// Created from a row in the ModuleRef table /// sealed class ModuleRefMD : ModuleRef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.ModuleRef, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this ModuleRef row /// Row ID /// If is null /// If is invalid public ModuleRefMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.ModuleRefTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("ModuleRef rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; this.module = readerModule; uint name = readerModule.TablesStream.ReadModuleRefRow2(origRid); this.name = readerModule.StringsStream.ReadNoNull(name); } } } dnlib-2.1_VS2010/src/DotNet/NativeType.cs000066400000000000000000000056341325033663500200000ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Native types used by field marshals. See CorHdr.h/CorNativeType /// public enum NativeType : uint { /// Deprecated End = 0x00, /// void Void = 0x01, /// bool Boolean = 0x02, /// int8 I1 = 0x03, /// unsigned int8 U1 = 0x04, /// int16 I2 = 0x05, /// unsigned int16 U2 = 0x06, /// int32 I4 = 0x07, /// unsigned int32 U4 = 0x08, /// int64 I8 = 0x09, /// unsigned int64 U8 = 0x0A, /// float32 R4 = 0x0B, /// float64 R8 = 0x0C, /// syschar SysChar = 0x0D, /// variant Variant = 0x0E, /// currency Currency = 0x0F, /// ptr Ptr = 0x10, /// decimal Decimal = 0x11, /// date Date = 0x12, /// bstr BStr = 0x13, /// lpstr LPStr = 0x14, /// lpwstr LPWStr = 0x15, /// lptstr LPTStr = 0x16, /// fixed sysstring FixedSysString = 0x17, /// objectref ObjectRef = 0x18, /// iunknown IUnknown = 0x19, /// idispatch IDispatch = 0x1A, /// struct Struct = 0x1B, /// interface IntF = 0x1C, /// safearray SafeArray = 0x1D, /// fixed array FixedArray = 0x1E, /// int Int = 0x1F, /// uint UInt = 0x20, /// nested struct NestedStruct = 0x21, /// byvalstr ByValStr = 0x22, /// ansi bstr ANSIBStr = 0x23, /// tbstr TBStr = 0x24, /// variant bool VariantBool = 0x25, /// func Func = 0x26, /// as any ASAny = 0x28, /// array Array = 0x2A, /// lpstruct LPStruct = 0x2B, /// custom marshaler CustomMarshaler = 0x2C, /// error Error = 0x2D, /// iinspectable IInspectable = 0x2E, /// hstring HString = 0x2F, /// UTF-8 encoded string LPUTF8Str = 0x30, /// first invalid element type Max = 0x50, /// Value wasn't present in the blob NotInitialized = 0xFFFFFFFE, /// Raw marshal blob type RawBlob = 0xFFFFFFFF, } } dnlib-2.1_VS2010/src/DotNet/NullResolver.cs000066400000000000000000000016241325033663500203370ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// A resolver that always fails /// public sealed class NullResolver : IAssemblyResolver, IResolver { /// /// The one and only instance of this type /// public static readonly NullResolver Instance = new NullResolver(); NullResolver() { } /// public AssemblyDef Resolve(IAssembly assembly, ModuleDef sourceModule) { return null; } /// public bool AddToCache(AssemblyDef asm) { return true; } /// public bool Remove(AssemblyDef asm) { return false; } /// public void Clear() { } /// public TypeDef Resolve(TypeRef typeRef, ModuleDef sourceModule) { return null; } /// public IMemberForwarded Resolve(MemberRef memberRef) { return null; } } } dnlib-2.1_VS2010/src/DotNet/PInvokeAttributes.cs000066400000000000000000000030521325033663500213220ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// P/Invoke attributes, see CorHdr.h/CorPinvokeMap /// [Flags] public enum PInvokeAttributes : ushort { /// Pinvoke is to use the member name as specified. NoMangle = 0x0001, /// Use this mask to retrieve the CharSet information. CharSetMask = 0x0006, /// CharSetNotSpec = 0x0000, /// CharSetAnsi = 0x0002, /// CharSetUnicode = 0x0004, /// CharSetAuto = 0x0006, /// BestFitUseAssem = 0x0000, /// BestFitEnabled = 0x0010, /// BestFitDisabled = 0x0020, /// BestFitMask = 0x0030, /// ThrowOnUnmappableCharUseAssem = 0x0000, /// ThrowOnUnmappableCharEnabled = 0x1000, /// ThrowOnUnmappableCharDisabled = 0x2000, /// ThrowOnUnmappableCharMask = 0x3000, /// Information about target function. Not relevant for fields. SupportsLastError = 0x0040, /// CallConvMask = 0x0700, /// Pinvoke will use native callconv appropriate to target windows platform. CallConvWinapi = 0x0100, /// CallConvCdecl = 0x0200, /// CallConvStdcall = 0x0300, /// CallConvStdCall = CallConvStdcall, /// In M9, pinvoke will raise exception. CallConvThiscall = 0x0400, /// CallConvFastcall = 0x0500, } } dnlib-2.1_VS2010/src/DotNet/ParamAttributes.cs000066400000000000000000000012741325033663500210130ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// Parameter flags. See CorHdr.h/CorParamAttr /// [Flags] public enum ParamAttributes : ushort { /// Param is [In] In = 0x0001, /// Param is [out] Out = 0x0002, /// Param is a locale identifier Lcid = 0x0004, /// Param is a return value Retval = 0x0008, /// Param is optional Optional = 0x0010, /// Param has default value. HasDefault = 0x1000, /// Param has FieldMarshal. HasFieldMarshal = 0x2000, } } dnlib-2.1_VS2010/src/DotNet/ParamDef.cs000066400000000000000000000305201325033663500173570ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the Param table /// [DebuggerDisplay("{Sequence} {Name}")] public abstract class ParamDef : IHasConstant, IHasCustomAttribute, IHasFieldMarshal, IHasCustomDebugInformation { /// /// The row id in its table /// protected uint rid; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// public MDToken MDToken { get { return new MDToken(Table.Param, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasConstantTag { get { return 1; } } /// public int HasCustomAttributeTag { get { return 4; } } /// public int HasFieldMarshalTag { get { return 1; } } /// /// Gets the declaring method /// public MethodDef DeclaringMethod { get { return declaringMethod; } internal set { declaringMethod = value; } } /// protected MethodDef declaringMethod; /// /// From column Param.Flags /// public ParamAttributes Attributes { get { return (ParamAttributes)attributes; } set { attributes = (int)value; } } /// Attributes protected int attributes; /// /// From column Param.Sequence /// public ushort Sequence { get { return sequence; } set { sequence = value; } } /// protected ushort sequence; /// /// From column Param.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// public MarshalType MarshalType { get { if (!marshalType_isInitialized) InitializeMarshalType(); return marshalType; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif marshalType = value; marshalType_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected MarshalType marshalType; /// protected bool marshalType_isInitialized; void InitializeMarshalType() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (marshalType_isInitialized) return; marshalType = GetMarshalType_NoLock(); marshalType_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual MarshalType GetMarshalType_NoLock() { return null; } /// Reset protected void ResetMarshalType() { marshalType_isInitialized = false; } /// public Constant Constant { get { if (!constant_isInitialized) InitializeConstant(); return constant; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif constant = value; constant_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected Constant constant; /// protected bool constant_isInitialized; void InitializeConstant() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (constant_isInitialized) return; constant = GetConstant_NoLock(); constant_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual Constant GetConstant_NoLock() { return null; } /// Reset protected void ResetConstant() { constant_isInitialized = false; } /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 4; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// /// true if is not null /// public bool HasConstant { get { return Constant != null; } } /// /// Gets the constant element type or if there's no constant /// public ElementType ElementType { get { var c = Constant; return c == null ? ElementType.End : c.Type; } } /// /// true if is not null /// public bool HasMarshalType { get { return MarshalType != null; } } /// public string FullName { get { var n = name; if (UTF8String.IsNullOrEmpty(n)) return string.Format("A_{0}", sequence); return n.String; } } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyAttributes(bool set, ParamAttributes 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 IsIn { get { return ((ParamAttributes)attributes & ParamAttributes.In) != 0; } set { ModifyAttributes(value, ParamAttributes.In); } } /// /// Gets/sets the bit /// public bool IsOut { get { return ((ParamAttributes)attributes & ParamAttributes.Out) != 0; } set { ModifyAttributes(value, ParamAttributes.Out); } } /// /// Gets/sets the bit /// public bool IsLcid { get { return ((ParamAttributes)attributes & ParamAttributes.Lcid) != 0; } set { ModifyAttributes(value, ParamAttributes.Lcid); } } /// /// Gets/sets the bit /// public bool IsRetval { get { return ((ParamAttributes)attributes & ParamAttributes.Retval) != 0; } set { ModifyAttributes(value, ParamAttributes.Retval); } } /// /// Gets/sets the bit /// public bool IsOptional { get { return ((ParamAttributes)attributes & ParamAttributes.Optional) != 0; } set { ModifyAttributes(value, ParamAttributes.Optional); } } /// /// Gets/sets the bit /// public bool HasDefault { get { return ((ParamAttributes)attributes & ParamAttributes.HasDefault) != 0; } set { ModifyAttributes(value, ParamAttributes.HasDefault); } } /// /// Gets/sets the bit /// public bool HasFieldMarshal { get { return ((ParamAttributes)attributes & ParamAttributes.HasFieldMarshal) != 0; } set { ModifyAttributes(value, ParamAttributes.HasFieldMarshal); } } } /// /// A Param row created by the user and not present in the original .NET file /// public class ParamDefUser : ParamDef { /// /// Default constructor /// public ParamDefUser() { } /// /// Constructor /// /// Name public ParamDefUser(UTF8String name) : this(name, 0) { } /// /// Constructor /// /// Name /// Sequence public ParamDefUser(UTF8String name, ushort sequence) : this(name, sequence, 0) { } /// /// Constructor /// /// Name /// Sequence /// Flags public ParamDefUser(UTF8String name, ushort sequence, ParamAttributes flags) { this.name = name; this.sequence = sequence; this.attributes = (int)flags; } } /// /// Created from a row in the Param table /// sealed class ParamDefMD : ParamDef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; /// public uint OrigRid { get { return origRid; } } /// protected override MarshalType GetMarshalType_NoLock() { return readerModule.ReadMarshalType(Table.Param, origRid, GenericParamContext.Create(declaringMethod)); } /// protected override Constant GetConstant_NoLock() { return readerModule.ResolveConstant(readerModule.MetaData.GetConstantRid(Table.Param, origRid)); } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.Param, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), GenericParamContext.Create(declaringMethod), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this Param row /// Row ID /// If is null /// If is invalid public ParamDefMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.ParamTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("Param rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; uint name = readerModule.TablesStream.ReadParamRow(origRid, out this.attributes, out this.sequence); this.name = readerModule.StringsStream.ReadNoNull(name); this.declaringMethod = readerModule.GetOwner(this); } internal ParamDefMD InitializeAll() { MemberMDInitializer.Initialize(DeclaringMethod); MemberMDInitializer.Initialize(Attributes); MemberMDInitializer.Initialize(Sequence); MemberMDInitializer.Initialize(Name); MemberMDInitializer.Initialize(MarshalType); MemberMDInitializer.Initialize(Constant); MemberMDInitializer.Initialize(CustomAttributes); return this; } } } dnlib-2.1_VS2010/src/DotNet/ParameterList.cs000066400000000000000000000373131325033663500204630ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A list of all method parameters /// [DebuggerDisplay("Count = {Count}")] public sealed class ParameterList : ThreadSafe.IList { readonly MethodDef method; readonly List parameters; readonly Parameter hiddenThisParameter; ParamDef hiddenThisParamDef; readonly Parameter returnParameter; int methodSigIndexBase; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// /// Gets the owner method /// public MethodDef Method { get { return method; } } /// /// Gets the number of parameters, including a possible hidden 'this' parameter /// public int Count { get { #if THREAD_SAFE theLock.EnterReadLock(); try { return ((ThreadSafe.IList)this).Count_NoLock; } finally { theLock.ExitReadLock(); } #else return parameters.Count; #endif } } /// /// Gets the index of the first parameter that is present in the method signature. /// If this is a static method, the value is 0, else it's an instance method so the /// index is 1 since the first parameter is the hidden 'this' parameter. /// public int MethodSigIndexBase { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return methodSigIndexBase == 1 ? 1 : 0; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } } /// /// Gets the N'th parameter /// /// The parameter index public Parameter this[int index] { get { #if THREAD_SAFE theLock.EnterReadLock(); try { return ((ThreadSafe.IList)this).Get_NoLock(index); } finally { theLock.ExitReadLock(); } #else return parameters[index]; #endif } set { throw new NotSupportedException(); } } /// /// Gets the method return parameter /// public Parameter ReturnParameter { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return returnParameter; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } } /// /// Constructor /// /// The method with all parameters /// 's declaring type public ParameterList(MethodDef method, TypeDef declaringType) { this.method = method; this.parameters = new List(); this.methodSigIndexBase = -1; this.hiddenThisParameter = new Parameter(this, 0, Parameter.HIDDEN_THIS_METHOD_SIG_INDEX); this.returnParameter = new Parameter(this, -1, Parameter.RETURN_TYPE_METHOD_SIG_INDEX); UpdateThisParameterType(declaringType); UpdateParameterTypes(); } /// /// Should be called when the method's declaring type has changed /// /// Method declaring type internal void UpdateThisParameterType(TypeDef methodDeclaringType) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (methodDeclaringType == null) hiddenThisParameter.SetType(false, null); else if (methodDeclaringType.IsValueType) hiddenThisParameter.SetType(false, new ByRefSig(new ValueTypeSig(methodDeclaringType))); else hiddenThisParameter.SetType(false, new ClassSig(methodDeclaringType)); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Should be called when the method sig has changed /// public void UpdateParameterTypes() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var sig = method.MethodSig; if (sig == null) { methodSigIndexBase = -1; parameters.Clear(); return; } if (UpdateThisParameter_NoLock(sig)) parameters.Clear(); returnParameter.SetType(false, sig.RetType); sig.Params.ExecuteLocked(null, (tsList, arg) => { ResizeParameters_NoLock(tsList.Count_NoLock() + methodSigIndexBase); if (methodSigIndexBase > 0) parameters[0] = hiddenThisParameter; for (int i = 0; i < tsList.Count_NoLock(); i++) parameters[i + methodSigIndexBase].SetType(true, tsList.Get_NoLock(i)); return null; }); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } bool UpdateThisParameter_NoLock(MethodSig methodSig) { int newIndex; if (methodSig == null) newIndex = -1; else newIndex = methodSig.ImplicitThis ? 1 : 0; if (methodSigIndexBase == newIndex) return false; methodSigIndexBase = newIndex; return true; } void ResizeParameters_NoLock(int length) { if (parameters.Count == length) return; if (parameters.Count < length) { for (int i = parameters.Count; i < length; i++) parameters.Add(new Parameter(this, i, i - methodSigIndexBase)); } else { while (parameters.Count > length) parameters.RemoveAt(parameters.Count - 1); } } internal ParamDef FindParamDef(Parameter param) { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return FindParamDef_NoLock(param); #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } ParamDef FindParamDef_NoLock(Parameter param) { int seq; if (param.IsReturnTypeParameter) seq = 0; else if (param.IsNormalMethodParameter) seq = param.MethodSigIndex + 1; else return hiddenThisParamDef; foreach (var paramDef in method.ParamDefs.GetSafeEnumerable()) { if (paramDef != null && paramDef.Sequence == seq) return paramDef; } return null; } internal void TypeUpdated(Parameter param, bool noParamsLock) { var sig = method.MethodSig; if (sig == null) return; int index = param.MethodSigIndex; if (index == Parameter.RETURN_TYPE_METHOD_SIG_INDEX) sig.RetType = param.Type; else if (index >= 0) { if (noParamsLock) sig.Params.Set_NoLock(index, param.Type); else sig.Params.Set(index, param.Type); } } internal void CreateParamDef(Parameter param) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var paramDef = FindParamDef_NoLock(param); if (paramDef != null) return; if (param.IsHiddenThisParameter) { hiddenThisParamDef = UpdateRowId_NoLock(new ParamDefUser(UTF8String.Empty, ushort.MaxValue, 0)); return; } int seq = param.IsReturnTypeParameter ? 0 : param.MethodSigIndex + 1; paramDef = UpdateRowId_NoLock(new ParamDefUser(UTF8String.Empty, (ushort)seq, 0)); method.ParamDefs.Add(paramDef); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } ParamDef UpdateRowId_NoLock(ParamDef pd) { var dt = method.DeclaringType; if (dt == null) return pd; var module = dt.Module; if (module == null) return pd; return module.UpdateRowId(pd); } /// public int IndexOf(Parameter item) { #if THREAD_SAFE theLock.EnterReadLock(); try { return ((ThreadSafe.IList)this).IndexOf_NoLock(item); } finally { theLock.ExitReadLock(); } #else return parameters.IndexOf(item); #endif } void IList.Insert(int index, Parameter item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } void ICollection.Add(Parameter item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(Parameter item) { #if THREAD_SAFE theLock.EnterReadLock(); try { return ((ThreadSafe.IList)this).Contains_NoLock(item); } finally { theLock.ExitReadLock(); } #else return parameters.Contains(item); #endif } void ICollection.CopyTo(Parameter[] array, int arrayIndex) { #if THREAD_SAFE theLock.EnterReadLock(); try { ((ThreadSafe.IList)this).CopyTo_NoLock(array, arrayIndex); } finally { theLock.ExitReadLock(); } #else parameters.CopyTo(array, arrayIndex); #endif } bool ICollection.IsReadOnly { get { return true; } } bool ICollection.Remove(Parameter item) { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { #if THREAD_SAFE theLock.EnterReadLock(); try { return ((ThreadSafe.IList)this).GetEnumerator_NoLock(); } finally { theLock.ExitReadLock(); } #else return parameters.GetEnumerator(); #endif } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } #if THREAD_SAFE int ThreadSafe.IList.IndexOf_NoLock(Parameter item) { return parameters.IndexOf(item); } void ThreadSafe.IList.Insert_NoLock(int index, Parameter item) { throw new NotSupportedException(); } void ThreadSafe.IList.RemoveAt_NoLock(int index) { throw new NotSupportedException(); } Parameter ThreadSafe.IList.Get_NoLock(int index) { return parameters[index]; } void ThreadSafe.IList.Set_NoLock(int index, Parameter value) { throw new NotSupportedException(); } void ThreadSafe.IList.Add_NoLock(Parameter item) { throw new NotSupportedException(); } void ThreadSafe.IList.Clear_NoLock() { throw new NotSupportedException(); } bool ThreadSafe.IList.Contains_NoLock(Parameter item) { return parameters.Contains(item); } void ThreadSafe.IList.CopyTo_NoLock(Parameter[] array, int arrayIndex) { parameters.CopyTo(array, arrayIndex); } bool ThreadSafe.IList.Remove_NoLock(Parameter item) { throw new NotSupportedException(); } IEnumerator ThreadSafe.IList.GetEnumerator_NoLock() { return parameters.GetEnumerator(); } int ThreadSafe.IList.Count_NoLock { get { return parameters.Count; } } bool ThreadSafe.IList.IsReadOnly_NoLock { get { return true; } } TRetType ThreadSafe.IList.ExecuteLocked(TArgType arg, ExecuteLockedDelegate handler) { theLock.EnterWriteLock(); try { return handler(this, arg); } finally { theLock.ExitWriteLock(); } } #endif } /// /// A method parameter /// public sealed class Parameter : IVariable { readonly ParameterList parameterList; TypeSig typeSig; readonly int paramIndex; readonly int methodSigIndex; /// /// The hidden 'this' parameter's /// public const int HIDDEN_THIS_METHOD_SIG_INDEX = -2; /// /// The return type parameter's /// public const int RETURN_TYPE_METHOD_SIG_INDEX = -1; /// /// Gets the parameter index. If the method has a hidden 'this' parameter, that parameter /// has index 0 and the remaining parameters in the method signature start from index 1. /// The method return parameter has index -1. /// public int Index { get { return paramIndex; } } /// /// Gets the index of the parameter in the method signature. See also /// and /// public int MethodSigIndex { get { return methodSigIndex; } } /// /// true if it's a normal visible method parameter, i.e., it's not the hidden /// 'this' parameter and it's not the method return type parameter. /// public bool IsNormalMethodParameter { get { return methodSigIndex >= 0; } } /// /// true if it's the hidden 'this' parameter /// public bool IsHiddenThisParameter { get { return methodSigIndex == HIDDEN_THIS_METHOD_SIG_INDEX; } } /// /// true if it's the method return type parameter /// public bool IsReturnTypeParameter { get { return methodSigIndex == RETURN_TYPE_METHOD_SIG_INDEX; } } /// /// Gets the parameter type /// public TypeSig Type { get { return typeSig; } set { typeSig = value; if (parameterList != null) parameterList.TypeUpdated(this, false); } } /// /// This method does exactly what the setter does except that it /// uses the no-lock method if is true. /// /// true if MethodSig.Params lock is being held by /// us /// internal void SetType(bool noParamsLock, TypeSig type) { typeSig = type; if (parameterList != null) parameterList.TypeUpdated(this, noParamsLock); } /// /// Gets the owner method /// public MethodDef Method { get { return parameterList == null ? null : parameterList.Method; } } /// /// Gets the or null if not present /// public ParamDef ParamDef { get { return parameterList == null ? null : parameterList.FindParamDef(this); } } /// /// true if it has a /// public bool HasParamDef { get { return ParamDef != null; } } /// /// Gets the name from . If is null, /// an empty string is returned. /// public string Name { get { var paramDef = ParamDef; return paramDef == null ? string.Empty : UTF8String.ToSystemStringOrEmpty(paramDef.Name); } set { var paramDef = ParamDef; if (paramDef != null) paramDef.Name = value; } } /// /// Constructor /// /// Parameter index public Parameter(int paramIndex) { this.paramIndex = paramIndex; this.methodSigIndex = paramIndex; } /// /// Constructor /// /// Parameter index /// Parameter type public Parameter(int paramIndex, TypeSig type) { this.paramIndex = paramIndex; this.methodSigIndex = paramIndex; this.typeSig = type; } /// /// Constructor /// /// Parameter index (0 is hidden this param if it exists) /// Index in method signature public Parameter(int paramIndex, int methodSigIndex) { this.paramIndex = paramIndex; this.methodSigIndex = methodSigIndex; } /// /// Constructor /// /// Parameter index (0 is hidden this param if it exists) /// Index in method signature /// Parameter type public Parameter(int paramIndex, int methodSigIndex, TypeSig type) { this.paramIndex = paramIndex; this.methodSigIndex = methodSigIndex; this.typeSig = type; } internal Parameter(ParameterList parameterList, int paramIndex, int methodSigIndex) { this.parameterList = parameterList; this.paramIndex = paramIndex; this.methodSigIndex = methodSigIndex; } /// /// Creates a if it doesn't already exist /// public void CreateParamDef() { if (parameterList != null) parameterList.CreateParamDef(this); } /// public override string ToString() { var name = Name; if (string.IsNullOrEmpty(name)) { if (IsReturnTypeParameter) return "RET_PARAM"; return string.Format("A_{0}", paramIndex); } return name; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/000077500000000000000000000000001325033663500160565ustar00rootroot00000000000000dnlib-2.1_VS2010/src/DotNet/Pdb/CustomDebugInfoGuids.cs000066400000000000000000000025001325033663500224330ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet.Pdb { /// /// Custom debug info guids /// public static class CustomDebugInfoGuids { #pragma warning disable 1591 // Missing XML comment for publicly visible type or member // Roslyn: PortableCustomDebugInfoKinds.cs public static readonly Guid AsyncMethodSteppingInformationBlob = new Guid("54FD2AC5-E925-401A-9C2A-F94F171072F8"); public static readonly Guid DefaultNamespace = new Guid("58B2EAB6-209F-4E4E-A22C-B2D0F910C782"); public static readonly Guid DynamicLocalVariables = new Guid("83C563C4-B4F3-47D5-B824-BA5441477EA8"); public static readonly Guid EmbeddedSource = new Guid("0E8A571B-6926-466E-B4AD-8AB04611F5FE"); public static readonly Guid EncLambdaAndClosureMap = new Guid("A643004C-0240-496F-A783-30D64F4979DE"); public static readonly Guid EncLocalSlotMap = new Guid("755F52A8-91C5-45BE-B4B8-209571E552BD"); public static readonly Guid SourceLink = new Guid("CC110556-A091-4D38-9FEC-25AB9A351A6A"); public static readonly Guid StateMachineHoistedLocalScopes = new Guid("6DA9A61E-F8C7-4874-BE62-68BC5630DF71"); public static readonly Guid TupleElementNames = new Guid("ED9FDF71-8879-4747-8ED3-FE5EDE3CE710"); #pragma warning restore 1591 // Missing XML comment for publicly visible type or member } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/000077500000000000000000000000001325033663500166075ustar00rootroot00000000000000dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/ComInterfaces.cs000066400000000000000000001052131325033663500216620ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; // Dss = Diagnostics Symbol Store = http://msdn.microsoft.com/en-us/library/ms404519.aspx namespace dnlib.DotNet.Pdb.Dss { [ComVisible(true), ComImport, Guid("809C652E-7396-11D2-9771-00A0C9B4D50C"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IMetaDataDispenser { void DefineScope([In] ref Guid rclsid, [In] uint dwCreateFlags, [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.IUnknown)] out object ppIUnk); void OpenScope([In, MarshalAs(UnmanagedType.LPWStr)] string szScope, [In] uint dwOpenFlags, [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.IUnknown)] out object ppIUnk); void OpenScopeOnMemory([In] IntPtr pData, [In] uint cbData, [In] uint dwOpenFlags, [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.IUnknown)] out object ppIUnk); } [ComVisible(true), ComImport, Guid("AA544D42-28CB-11D3-BD22-0000F80849BD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ISymUnmanagedBinder { [PreserveSig] int GetReaderForFile([In, MarshalAs(UnmanagedType.IUnknown)] object importer, [In, MarshalAs(UnmanagedType.LPWStr)] string fileName, [In, MarshalAs(UnmanagedType.LPWStr)] string searchPath, [Out] out ISymUnmanagedReader pRetVal); [PreserveSig] int GetReaderFromStream([In, MarshalAs(UnmanagedType.IUnknown)] object importer, [In] IStream pstream, [Out] out ISymUnmanagedReader pRetVal); } [ComVisible(true), ComImport, Guid("B4CE6286-2A6B-3712-A3B7-1EE1DAD467B5"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ISymUnmanagedReader { void GetDocument([In, MarshalAs(UnmanagedType.LPWStr)] string url, [In] Guid language, [In] Guid languageVendor, [In] Guid documentType, [Out] out ISymUnmanagedDocument pRetVal); void GetDocuments([In] uint cDocs, [Out] out uint pcDocs, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedDocument[] pDocs); [PreserveSig] int GetUserEntryPoint([Out] out uint pToken); [PreserveSig] int GetMethod([In] uint token, [Out] out ISymUnmanagedMethod retVal); [PreserveSig] int GetMethodByVersion([In] uint token, [In] int version, [Out] out ISymUnmanagedMethod pRetVal); void GetVariables([In] uint parent, [In] uint cVars, [Out] out uint pcVars, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ISymUnmanagedVariable[] pVars); void GetGlobalVariables([In] uint cVars, [Out] out uint pcVars, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] pVars); [PreserveSig] int GetMethodFromDocumentPosition([In] ISymUnmanagedDocument document, [In] uint line, [In] uint column, [Out] out ISymUnmanagedMethod pRetVal); void GetSymAttribute([In] uint parent, [In, MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint cBuffer, [Out] out uint pcBuffer, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] buffer); void GetNamespaces([In] uint cNameSpaces, [Out] out uint pcNameSpaces, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedNamespace[] namespaces); void Initialize([In, MarshalAs(UnmanagedType.IUnknown)] object importer, [In, MarshalAs(UnmanagedType.LPWStr)] string filename, [In, MarshalAs(UnmanagedType.LPWStr)] string searchPath, [In] IStream pIStream); void UpdateSymbolStore([In, MarshalAs(UnmanagedType.LPWStr)] string filename, [In] IStream pIStream); void ReplaceSymbolStore([In, MarshalAs(UnmanagedType.LPWStr)] string filename, [In] IStream pIStream); void GetSymbolStoreFileName([In] uint cchName, [Out] out uint pcchName, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] szName); void GetMethodsFromDocumentPosition([In] ISymUnmanagedDocument document, [In] uint line, [In] uint column, [In] uint cMethod, [Out] out uint pcMethod, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] ISymUnmanagedMethod[] pRetVal); void GetDocumentVersion([In] ISymUnmanagedDocument pDoc, [Out] out int version, [Out] out bool pbCurrent); void GetMethodVersion([In] ISymUnmanagedMethod pMethod, [Out] out int version); } [ComVisible(true), ComImport, Guid("40DE4037-7C81-3E1E-B022-AE1ABFF2CA08"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ISymUnmanagedDocument { void GetURL([In] uint cchUrl, [Out] out uint pcchUrl, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] szUrl); void GetDocumentType([Out] out Guid pRetVal); void GetLanguage([Out] out Guid pRetVal); void GetLanguageVendor([Out] out Guid pRetVal); void GetCheckSumAlgorithmId([Out] out Guid pRetVal); void GetCheckSum([In] uint cData, [Out] out uint pcData, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] data); void FindClosestLine([In] uint line, [Out] out uint pRetVal); void HasEmbeddedSource([Out] out bool pRetVal); void GetSourceLength([Out] out uint pRetVal); void GetSourceRange([In] uint startLine, [In] uint startColumn, [In] uint endLine, [In] uint endColumn, [In] uint cSourceBytes, [Out] out uint pcSourceBytes, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] source); } [ComVisible(true), ComImport, Guid("B62B923C-B500-3158-A543-24F307A8B7E1"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ISymUnmanagedMethod { void GetToken([Out] out uint pToken); void GetSequencePointCount([Out] out uint pRetVal); void GetRootScope([Out] out ISymUnmanagedScope pRetVal); void GetScopeFromOffset([In] uint offset, [Out] out ISymUnmanagedScope pRetVal); void GetOffset([In] ISymUnmanagedDocument document, [In] uint line, [In] uint column, [Out] out uint pRetVal); void GetRanges([In] ISymUnmanagedDocument document, [In] uint line, [In] uint column, [In] uint cRanges, [Out] out uint pcRanges, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] int[] ranges); void GetParameters([In] uint cParams, [Out] out uint pcParams, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] parameters); void GetNamespace([Out] out ISymUnmanagedNamespace pRetVal); void GetSourceStartEnd([In] ISymUnmanagedDocument[/*2*/] docs, [In] int[/*2*/] lines, [In] int[/*2*/] columns, [Out] out bool pRetVal); void GetSequencePoints([In] uint cPoints, [Out] out uint pcPoints, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] offsets, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedDocument[] documents, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] lines, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] columns, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] endLines, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] endColumns); } [ComVisible(true), ComImport, Guid("B20D55B3-532E-4906-87E7-25BD5734ABD2"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ISymUnmanagedAsyncMethod { bool IsAsyncMethod(); uint GetKickoffMethod(); bool HasCatchHandlerILOffset(); uint GetCatchHandlerILOffset(); uint GetAsyncStepInfoCount(); void GetAsyncStepInfo([In] uint cStepInfo, [Out] out uint pcStepInfo, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] yieldOffsets, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] breakpointOffset, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] breakpointMethod); } [ComVisible(true), ComImport, Guid("9F60EEBE-2D9A-3F7C-BF58-80BC991C60BB"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ISymUnmanagedVariable { void GetName([In] uint cchName, [Out] out uint pcchName, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] szName); void GetAttributes([Out] out uint pRetVal); void GetSignature([In] uint cSig, [Out] out uint pcSig, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] sig); void GetAddressKind([Out] out uint pRetVal); void GetAddressField1([Out] out uint pRetVal); void GetAddressField2([Out] out uint pRetVal); void GetAddressField3([Out] out uint pRetVal); void GetStartOffset([Out] out uint pRetVal); void GetEndOffset([Out] out uint pRetVal); } [ComVisible(true), ComImport, Guid("0DFF7289-54F8-11D3-BD28-0000F80849BD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ISymUnmanagedNamespace { void GetName([In] uint cchName, [Out] out uint pcchName, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] szName); void GetNamespaces([In] uint cNameSpaces, [Out] out uint pcNameSpaces, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedNamespace[] namespaces); void GetVariables([In] uint cVars, [Out] out uint pcVars, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] pVars); } [ComVisible(true), ComImport, Guid("68005D0F-B8E0-3B01-84D5-A11A94154942"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ISymUnmanagedScope { void GetMethod([Out] out ISymUnmanagedMethod pRetVal); void GetParent([Out] out ISymUnmanagedScope pRetVal); void GetChildren([In] uint cChildren, [Out] out uint pcChildren, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedScope[] children); void GetStartOffset([Out] out uint pRetVal); void GetEndOffset([Out] out uint pRetVal); void GetLocalCount([Out] out uint pRetVal); void GetLocals([In] uint cLocals, [Out] out uint pcLocals, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] locals); void GetNamespaces([In] uint cNameSpaces, [Out] out uint pcNameSpaces, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedNamespace[] namespaces); } [ComVisible(true), ComImport, Guid("AE932FBA-3FD8-4dba-8232-30A2309B02DB"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ISymUnmanagedScope2 : ISymUnmanagedScope { #pragma warning disable 0108 void GetMethod([Out] out ISymUnmanagedMethod pRetVal); void GetParent([Out] out ISymUnmanagedScope pRetVal); void GetChildren([In] uint cChildren, [Out] out uint pcChildren, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedScope[] children); void GetStartOffset([Out] out uint pRetVal); void GetEndOffset([Out] out uint pRetVal); void GetLocalCount([Out] out uint pRetVal); void GetLocals([In] uint cLocals, [Out] out uint pcLocals, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedVariable[] locals); void GetNamespaces([In] uint cNameSpaces, [Out] out uint pcNameSpaces, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedNamespace[] namespaces); #pragma warning restore 0108 uint GetConstantCount(); void GetConstants([In] uint cConstants, [Out] out uint pcConstants, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ISymUnmanagedConstant[] constants); } [ComVisible(true), ComImport, Guid("48B25ED8-5BAD-41bc-9CEE-CD62FABC74E9"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ISymUnmanagedConstant { void GetName([In] uint cchName, [Out] out uint pcchName, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] char[] szName); void GetValue(out object pValue); [PreserveSig] int GetSignature([In] uint cSig, [Out] out uint pcSig, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] sig); } [ComVisible(true), ComImport, Guid("7DAC8207-D3AE-4C75-9B67-92801A497D44"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IMetaDataImport { void CloseEnum(IntPtr hEnum); void CountEnum(IntPtr hEnum, ref uint pulCount); void ResetEnum(IntPtr hEnum, uint ulPos); void EnumTypeDefs(IntPtr phEnum, uint[] rTypeDefs, uint cMax, out uint pcTypeDefs); void EnumInterfaceImpls(ref IntPtr phEnum, uint td, uint[] rImpls, uint cMax, ref uint pcImpls); void EnumTypeRefs(ref IntPtr phEnum, uint[] rTypeRefs, uint cMax, ref uint pcTypeRefs); void FindTypeDefByName([In, MarshalAs(UnmanagedType.LPWStr)] string szTypeDef, [In] uint tkEnclosingClass, [Out] out uint ptd); void GetScopeProps([Out] IntPtr szName, [In] uint cchName, [Out] out uint pchName, [Out] out Guid pmvid); void GetModuleFromScope([Out] out uint pmd); unsafe void GetTypeDefProps([In] uint td, [In] ushort* szTypeDef, [In] uint cchTypeDef, [Out] uint* pchTypeDef, [Out] uint* pdwTypeDefFlags, [Out] uint* ptkExtends); void GetInterfaceImplProps([In] uint iiImpl, [Out] out uint pClass, [Out] out uint ptkIface); void GetTypeRefProps([In] uint tr, [Out] out uint ptkResolutionScope, [Out] IntPtr szName, [In] uint cchName, [Out] out uint pchName); void ResolveTypeRef(uint tr, ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppIScope, out uint ptd); void EnumMembers([In, Out] ref IntPtr phEnum, [In] uint cl, [Out] uint[] rMembers, [In] uint cMax, [Out] out uint pcTokens); void EnumMembersWithName([In, Out] ref IntPtr phEnum, [In] uint cl, [In] [MarshalAs(UnmanagedType.LPWStr)] string szName, [Out] uint[] rMembers, [In] uint cMax, [Out] out uint pcTokens); void EnumMethods([In, Out] ref IntPtr phEnum, [In] uint cl, [Out] uint[] rMethods, [In] uint cMax, [Out] out uint pcTokens); void EnumMethodsWithName([In, Out] ref IntPtr phEnum, [In] uint cl, [In] [MarshalAs(UnmanagedType.LPWStr)] string szName, uint[] rMethods, [In] uint cMax, [Out] out uint pcTokens); void EnumFields([In, Out] ref IntPtr phEnum, [In] uint cl, [Out] uint[] rFields, [In] uint cMax, [Out] out uint pcTokens); void EnumFieldsWithName([In, Out] ref IntPtr phEnum, [In] uint cl, [In] [MarshalAs(UnmanagedType.LPWStr)] string szName, [Out] uint[] rFields, [In] uint cMax, [Out] out uint pcTokens); void EnumParams([In, Out] ref IntPtr phEnum, [In] uint mb, [Out] uint[] rParams, [In] uint cMax, [Out] out uint pcTokens); void EnumMemberRefs([In, Out] ref IntPtr phEnum, [In] uint tkParent, [Out] uint[] rMemberRefs, [In] uint cMax, [Out] out uint pcTokens); void EnumMethodImpls([In, Out] ref IntPtr phEnum, [In] uint td, [Out] uint[] rMethodBody, [Out] uint[] rMethodDecl, [In] uint cMax, [Out] out uint pcTokens); void EnumPermissionSets([In, Out] ref IntPtr phEnum, [In] uint tk, [In] uint dwActions, [Out] uint[] rPermission, [In] uint cMax, [Out] out uint pcTokens); void FindMember([In] uint td, [In] [MarshalAs(UnmanagedType.LPWStr)] string szName, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, [Out] out uint pmb); void FindMethod([In] uint td, [In] [MarshalAs(UnmanagedType.LPWStr)] string szName, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, [Out] out uint pmb); void FindField([In] uint td, [In] [MarshalAs(UnmanagedType.LPWStr)] string szName, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, [Out] out uint pmb); void FindMemberRef([In] uint td, [In] [MarshalAs(UnmanagedType.LPWStr)] string szName, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, [Out] out uint pmr); unsafe void GetMethodProps(uint mb, uint* pClass, [In] ushort* szMethod, uint cchMethod, uint* pchMethod, uint* pdwAttr, [Out] IntPtr* ppvSigBlob, [Out] uint* pcbSigBlob, [Out] uint* pulCodeRVA, [Out] uint* pdwImplFlags); void GetMemberRefProps([In] uint mr, [Out] out uint ptk, [Out] IntPtr szMember, [In] uint cchMember, [Out] out uint pchMember, [Out] out IntPtr ppvSigBlob, [Out] out uint pbSig); void EnumProperties([In, Out] ref IntPtr phEnum, [In] uint td, [Out] uint[] rProperties, [In] uint cMax, [Out] out uint pcProperties); void EnumEvents([In, Out] ref IntPtr phEnum, [In] uint td, [Out] uint[] rEvents, [In] uint cMax, [Out] out uint pcEvents); void GetEventProps([In] uint ev, [Out] out uint pClass, [Out] [MarshalAs(UnmanagedType.LPWStr)] string szEvent, [In] uint cchEvent, [Out] out uint pchEvent, [Out] out uint pdwEventFlags, [Out] out uint ptkEventType, [Out] out uint pmdAddOn, [Out] out uint pmdRemoveOn, [Out] out uint pmdFire, [In, Out] uint[] rmdOtherMethod, [In] uint cMax, [Out] out uint pcOtherMethod); void EnumMethodSemantics([In, Out] ref IntPtr phEnum, [In] uint mb, [In, Out] uint[] rEventProp, [In] uint cMax, [Out] out uint pcEventProp); void GetMethodSemantics([In] uint mb, [In] uint tkEventProp, [Out] out uint pdwSemanticsFlags); void GetClassLayout([In] uint td, [Out] out uint pdwPackSize, [Out] out IntPtr rFieldOffset, [In] uint cMax, [Out] out uint pcFieldOffset, [Out] out uint pulClassSize); void GetFieldMarshal([In] uint tk, [Out] out IntPtr ppvNativeType, [Out] out uint pcbNativeType); void GetRVA(uint tk, out uint pulCodeRVA, out uint pdwImplFlags); void GetPermissionSetProps([In] uint pm, [Out] out uint pdwAction, [Out] out IntPtr ppvPermission, [Out] out uint pcbPermission); void GetSigFromToken([In] uint mdSig, [Out] out IntPtr ppvSig, [Out] out uint pcbSig); void GetModuleRefProps([In] uint mur, [Out] IntPtr szName, [In] uint cchName, [Out] out uint pchName); void EnumModuleRefs([In, Out] ref IntPtr phEnum, [Out] uint[] rModuleRefs, [In] uint cmax, [Out] out uint pcModuleRefs); void GetTypeSpecFromToken([In] uint typespec, [Out] out IntPtr ppvSig, [Out] out uint pcbSig); void GetNameFromToken([In] uint tk, [Out] out IntPtr pszUtf8NamePtr); void EnumUnresolvedMethods([In, Out] ref IntPtr phEnum, [Out] uint[] rMethods, [In] uint cMax, [Out] out uint pcTokens); void GetUserString([In] uint stk, [Out] IntPtr szString, [In] uint cchString, [Out] out uint pchString); void GetPinvokeMap([In] uint tk, [Out] out uint pdwMappingFlags, [Out] IntPtr szImportName, [In] uint cchImportName, [Out] out uint pchImportName, [Out] out uint pmrImportDLL); void EnumSignatures([In, Out] ref IntPtr phEnum, [Out] uint[] rSignatures, [In] uint cmax, [Out] out uint pcSignatures); void EnumTypeSpecs([In, Out] ref IntPtr phEnum, [Out] uint[] rTypeSpecs, [In] uint cmax, [Out] out uint pcTypeSpecs); void EnumUserStrings([In, Out] ref IntPtr phEnum, [Out] uint[] rStrings, [In] uint cmax, [Out] out uint pcStrings); void GetParamForMethodIndex([In] uint md, [In] uint ulParamSeq, [Out] out uint ppd); void EnumCustomAttributes([In, Out] IntPtr phEnum, [In] uint tk, [In] uint tkType, [Out] uint[] rCustomAttributes, [In] uint cMax, [Out] out uint pcCustomAttributes); void GetCustomAttributeProps([In] uint cv, [Out] out uint ptkObj, [Out] out uint ptkType, [Out] out IntPtr ppBlob, [Out] out uint pcbSize); void FindTypeRef([In] uint tkResolutionScope, [In] [MarshalAs(UnmanagedType.LPWStr)] string szName, [Out] out uint ptr); void GetMemberProps(uint mb, out uint pClass, IntPtr szMember, uint cchMember, out uint pchMember, out uint pdwAttr, [Out] out IntPtr ppvSigBlob, [Out] out uint pcbSigBlob, [Out] out uint pulCodeRVA, [Out] out uint pdwImplFlags, [Out] out uint pdwCPlusTypeFlag, [Out] out IntPtr ppValue, [Out] out uint pcchValue); void GetFieldProps(uint mb, out uint pClass, IntPtr szField, uint cchField, out uint pchField, out uint pdwAttr, [Out] out IntPtr ppvSigBlob, [Out] out uint pcbSigBlob, [Out] out uint pdwCPlusTypeFlag, [Out] out IntPtr ppValue, [Out] out uint pcchValue); void GetPropertyProps([In] uint prop, [Out] out uint pClass, [Out] IntPtr szProperty, [In] uint cchProperty, [Out] out uint pchProperty, [Out] out uint pdwPropFlags, [Out] out IntPtr ppvSig, [Out] out uint pbSig, [Out] out uint pdwCPlusTypeFlag, [Out] out IntPtr ppDefaultValue, [Out] out uint pcchDefaultValue, [Out] out uint pmdSetter, [Out] out uint pmdGetter, [In, Out] uint[] rmdOtherMethod, [In] uint cMax, [Out] out uint pcOtherMethod); void GetParamProps([In] uint tk, [Out] out uint pmd, [Out] out uint pulSequence, [Out] IntPtr szName, [Out] uint cchName, [Out] out uint pchName, [Out] out uint pdwAttr, [Out] out uint pdwCPlusTypeFlag, [Out] out IntPtr ppValue, [Out] out uint pcchValue); void GetCustomAttributeByName([In] uint tkObj, [In] [MarshalAs(UnmanagedType.LPWStr)] string szName, [Out] out IntPtr ppData, [Out] out uint pcbData); bool IsValidToken([In] uint tk); unsafe void GetNestedClassProps([In] uint tdNestedClass, [Out] uint* ptdEnclosingClass); void GetNativeCallConvFromSig([In] IntPtr pvSig, [In] uint cbSig, [Out] out uint pCallConv); void IsGlobal([In] uint pd, [Out] out int pbGlobal); } [ComVisible(true), ComImport, Guid("BA3FEE4C-ECB9-4E41-83B7-183FA41CD859"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IMetaDataEmit { void SetModuleProps([In] [MarshalAs(UnmanagedType.LPWStr)] string szName); void Save([In] [MarshalAs(UnmanagedType.LPWStr)] string szFile, [In] uint dwSaveFlags); void SaveToStream([In] IStream pIStream, [In] uint dwSaveFlags); void GetSaveSize([In] int fSave, [Out] out uint pdwSaveSize); void DefineTypeDef([In] [MarshalAs(UnmanagedType.LPWStr)] string szTypeDef, [In] uint dwTypeDefFlags, [In] uint tkExtends, [In] uint[] rtkImplements, [Out] out uint ptd); void DefineNestedType([In] [MarshalAs(UnmanagedType.LPWStr)] string szTypeDef, [In] uint dwTypeDefFlags, [In] uint tkExtends, [In] uint[] rtkImplements, [In] uint tdEncloser, [Out] out uint ptd); void SetHandler([In, MarshalAs(UnmanagedType.IUnknown)] object pUnk); void DefineMethod(uint td, [MarshalAs(UnmanagedType.LPWStr)] string szName, uint dwMethodFlags, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, uint ulCodeRVA, uint dwImplFlags, out uint pmd); void DefineMethodImpl([In] uint td, [In] uint tkBody, [In] uint tkDecl); void DefineTypeRefByName([In] uint tkResolutionScope, [In] [MarshalAs(UnmanagedType.LPWStr)] string szName, [Out] out uint ptr); void DefineImportType([In] IntPtr pAssemImport, [In] IntPtr pbHashValue, [In] uint cbHashValue, [In] IMetaDataImport pImport, [In] uint tdImport, [In] IntPtr pAssemEmit, [Out] out uint ptr); void DefineMemberRef([In] uint tkImport, [In] [MarshalAs(UnmanagedType.LPWStr)] string szName, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, [Out] out uint pmr); void DefineImportMember([In] IntPtr pAssemImport, [In] IntPtr pbHashValue, [In] uint cbHashValue, [In] IMetaDataImport pImport, [In] uint mbMember, [In] IntPtr pAssemEmit, [In] uint tkParent, [Out] out uint pmr); void DefineEvent([In] uint td, [In] [MarshalAs(UnmanagedType.LPWStr)] string szEvent, [In] uint dwEventFlags, [In] uint tkEventType, [In] uint mdAddOn, [In] uint mdRemoveOn, [In] uint mdFire, [In] uint[] rmdOtherMethods, [Out] out uint pmdEvent); void SetClassLayout([In] uint td, [In] uint dwPackSize, [In] IntPtr rFieldOffsets, [In] uint ulClassSize); void DeleteClassLayout([In] uint td); void SetFieldMarshal([In] uint tk, [In] IntPtr pvNativeType, [In] uint cbNativeType); void DeleteFieldMarshal([In] uint tk); void DefinePermissionSet([In] uint tk, [In] uint dwAction, [In] IntPtr pvPermission, [In] uint cbPermission, [Out] out uint ppm); void SetRVA([In] uint md, [In] uint ulRVA); void GetTokenFromSig([In] IntPtr pvSig, [In] uint cbSig, [Out] out uint pmsig); void DefineModuleRef([In] [MarshalAs(UnmanagedType.LPWStr)] string szName, [Out] out uint pmur); void SetParent([In] uint mr, [In] uint tk); void GetTokenFromTypeSpec([In] IntPtr pvSig, [In] uint cbSig, [Out] out uint ptypespec); void SaveToMemory([Out] out IntPtr pbData, [In] uint cbData); void DefineUserString([In] [MarshalAs(UnmanagedType.LPWStr)] string szString, [In] uint cchString, [Out] out uint pstk); void DeleteToken([In] uint tkObj); void SetMethodProps([In] uint md, [In] uint dwMethodFlags, [In] uint ulCodeRVA, [In] uint dwImplFlags); void SetTypeDefProps([In] uint td, [In] uint dwTypeDefFlags, [In] uint tkExtends, [In] uint[] rtkImplements); void SetEventProps([In] uint ev, [In] uint dwEventFlags, [In] uint tkEventType, [In] uint mdAddOn, [In] uint mdRemoveOn, [In] uint mdFire, [In] uint[] rmdOtherMethods); void SetPermissionSetProps([In] uint tk, [In] uint dwAction, [In] IntPtr pvPermission, [In] uint cbPermission, [Out] out uint ppm); void DefinePinvokeMap([In] uint tk, [In] uint dwMappingFlags, [In] [MarshalAs(UnmanagedType.LPWStr)] string szImportName, [In] uint mrImportDLL); void SetPinvokeMap([In] uint tk, [In] uint dwMappingFlags, [In] [MarshalAs(UnmanagedType.LPWStr)] string szImportName, [In] uint mrImportDLL); void DeletePinvokeMap([In] uint tk); void DefineCustomAttribute([In] uint tkOwner, [In] uint tkCtor, [In] IntPtr pCustomAttribute, [In] uint cbCustomAttribute, [Out] out uint pcv); void SetCustomAttributeValue([In] uint pcv, [In] IntPtr pCustomAttribute, [In] uint cbCustomAttribute); void DefineField(uint td, [MarshalAs(UnmanagedType.LPWStr)] string szName, uint dwFieldFlags, [In] IntPtr pvSigBlob, [In] uint cbSigBlob, [In] uint dwCPlusTypeFlag, [In] IntPtr pValue, [In] uint cchValue, [Out] out uint pmd); void DefineProperty([In] uint td, [In] [MarshalAs(UnmanagedType.LPWStr)] string szProperty, [In] uint dwPropFlags, [In] IntPtr pvSig, [In] uint cbSig, [In] uint dwCPlusTypeFlag, [In] IntPtr pValue, [In] uint cchValue, [In] uint mdSetter, [In] uint mdGetter, [In] uint[] rmdOtherMethods, [Out] out uint pmdProp); void DefineParam([In] uint md, [In] uint ulParamSeq, [In] [MarshalAs(UnmanagedType.LPWStr)] string szName, [In] uint dwParamFlags, [In] uint dwCPlusTypeFlag, [In] IntPtr pValue, [In] uint cchValue, [Out] out uint ppd); void SetFieldProps([In] uint fd, [In] uint dwFieldFlags, [In] uint dwCPlusTypeFlag, [In] IntPtr pValue, [In] uint cchValue); void SetPropertyProps([In] uint pr, [In] uint dwPropFlags, [In] uint dwCPlusTypeFlag, [In] IntPtr pValue, [In] uint cchValue, [In] uint mdSetter, [In] uint mdGetter, [In] uint[] rmdOtherMethods); void SetParamProps([In] uint pd, [In] [MarshalAs(UnmanagedType.LPWStr)] string szName, [In] uint dwParamFlags, [In] uint dwCPlusTypeFlag, [Out] IntPtr pValue, [In] uint cchValue); void DefineSecurityAttributeSet([In] uint tkObj, [In] IntPtr rSecAttrs, [In] uint cSecAttrs, [Out] out uint pulErrorAttr); void ApplyEditAndContinue([In, MarshalAs(UnmanagedType.IUnknown)] object pImport); void TranslateSigWithScope([In] IntPtr pAssemImport, [In] IntPtr pbHashValue, [In] uint cbHashValue, [In] IMetaDataImport import, [In] IntPtr pbSigBlob, [In] uint cbSigBlob, [In] IntPtr pAssemEmit, [In] IMetaDataEmit emit, [Out] IntPtr pvTranslatedSig, uint cbTranslatedSigMax, [Out] out uint pcbTranslatedSig); void SetMethodImplFlags([In] uint md, uint dwImplFlags); void SetFieldRVA([In] uint fd, [In] uint ulRVA); void Merge([In] IMetaDataImport pImport, [In] IntPtr pHostMapToken, [In, MarshalAs(UnmanagedType.IUnknown)] object pHandler); void MergeEnd(); } [ComVisible(true), ComImport, Guid("ED14AA72-78E2-4884-84E2-334293AE5214"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ISymUnmanagedWriter { void DefineDocument([In] [MarshalAs(UnmanagedType.LPWStr)] string url, [In] ref Guid language, [In] ref Guid languageVendor, [In] ref Guid documentType, [Out] out ISymUnmanagedDocumentWriter pRetVal); void SetUserEntryPoint([In] uint entryMethod); void OpenMethod([In] uint method); void CloseMethod(); void OpenScope([In] uint startOffset, [Out] out uint pRetVal); void CloseScope([In] uint endOffset); void SetScopeRange([In] uint scopeID, [In] uint startOffset, [In] uint endOffset); void DefineLocalVariable([In] [MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint cSig, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3, [In] uint startOffset, [In] uint endOffset); void DefineParameter([In] [MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint sequence, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void DefineField([In] uint parent, [In] [MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint cSig, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] signature, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void DefineGlobalVariable([In] [MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint cSig, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void Close(); void SetSymAttribute([In] uint parent, [In] [MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint cData, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] data); void OpenNamespace([In] [MarshalAs(UnmanagedType.LPWStr)] string name); void CloseNamespace(); void UsingNamespace([In] [MarshalAs(UnmanagedType.LPWStr)] string fullName); void SetMethodSourceRange([In] ISymUnmanagedDocumentWriter startDoc, [In] uint startLine, [In] uint startColumn, [In] ISymUnmanagedDocumentWriter endDoc, [In] uint endLine, [In] uint endColumn); void Initialize([In] IntPtr emitter, [In] [MarshalAs(UnmanagedType.LPWStr)] string filename, [In] IStream pIStream, [In] bool fFullBuild); void GetDebugInfo([Out] out IMAGE_DEBUG_DIRECTORY pIDD, [In] uint cData, [Out] out uint pcData, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data); void DefineSequencePoints([In] ISymUnmanagedDocumentWriter document, [In] uint spCount, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] offsets, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] lines, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] columns, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endLines, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endColumns); void RemapToken([In] uint oldToken, [In] uint newToken); void Initialize2([In, MarshalAs(UnmanagedType.IUnknown)] object emitter, [In] [MarshalAs(UnmanagedType.LPWStr)] string tempfilename, [In] IStream pIStream, [In] bool fFullBuild, [In] [MarshalAs(UnmanagedType.LPWStr)] string finalfilename); void DefineConstant([In] [MarshalAs(UnmanagedType.LPWStr)] string name, [In] object value, [In] uint cSig, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature); void Abort(); } #pragma warning disable 1591 [ComVisible(true), ComImport, Guid("0B97726E-9E6D-4F05-9A26-424022093CAA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface ISymUnmanagedWriter2 { void DefineDocument([In] [MarshalAs(UnmanagedType.LPWStr)] string url, [In] ref Guid language, [In] ref Guid languageVendor, [In] ref Guid documentType, [Out] out ISymUnmanagedDocumentWriter pRetVal); void SetUserEntryPoint([In] uint entryMethod); void OpenMethod([In] uint method); void CloseMethod(); void OpenScope([In] uint startOffset, [Out] out uint pRetVal); void CloseScope([In] uint endOffset); void SetScopeRange([In] uint scopeID, [In] uint startOffset, [In] uint endOffset); void DefineLocalVariable([In] [MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint cSig, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3, [In] uint startOffset, [In] uint endOffset); void DefineParameter([In] [MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint sequence, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void DefineField([In] uint parent, [In] [MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint cSig, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] signature, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void DefineGlobalVariable([In] [MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint cSig, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void Close(); void SetSymAttribute([In] uint parent, [In] [MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint cData, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] data); void OpenNamespace([In] [MarshalAs(UnmanagedType.LPWStr)] string name); void CloseNamespace(); void UsingNamespace([In] [MarshalAs(UnmanagedType.LPWStr)] string fullName); void SetMethodSourceRange([In] ISymUnmanagedDocumentWriter startDoc, [In] uint startLine, [In] uint startColumn, [In] ISymUnmanagedDocumentWriter endDoc, [In] uint endLine, [In] uint endColumn); void Initialize([In, MarshalAs(UnmanagedType.IUnknown)] object emitter, [In] [MarshalAs(UnmanagedType.LPWStr)] string filename, [In] IStream pIStream, [In] bool fFullBuild); void GetDebugInfo([Out] out IMAGE_DEBUG_DIRECTORY pIDD, [In] uint cData, [Out] out uint pcData, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data); void DefineSequencePoints([In] ISymUnmanagedDocumentWriter document, [In] uint spCount, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] offsets, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] lines, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] columns, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endLines, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endColumns); void RemapToken([In] uint oldToken, [In] uint newToken); void Initialize2([In, MarshalAs(UnmanagedType.IUnknown)] object emitter, [In] [MarshalAs(UnmanagedType.LPWStr)] string tempfilename, [In] IStream pIStream, [In] bool fFullBuild, [In] [MarshalAs(UnmanagedType.LPWStr)] string finalfilename); void DefineConstant([In] [MarshalAs(UnmanagedType.LPWStr)] string name, [In] object value, [In] uint cSig, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature); void Abort(); void DefineLocalVariable2([In, MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint sigToken, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3, [In] uint startOffset, [In] uint endOffset); void DefineGlobalVariable2([In, MarshalAs(UnmanagedType.LPWStr)] string name, [In] uint attributes, [In] uint sigToken, [In] uint addrKind, [In] uint addr1, [In] uint addr2, [In] uint addr3); void DefineConstant2([In, MarshalAs(UnmanagedType.LPWStr)] string name, [In] object value, [In] uint sigToken); } #pragma warning restore 1591 #pragma warning disable 1591 [ComVisible(true), ComImport, Guid("B01FAFEB-C450-3A4D-BEEC-B4CEEC01E006"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface ISymUnmanagedDocumentWriter { void SetSource([In] uint sourceSize, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] source); void SetCheckSum([In] Guid algorithmId, [In] uint checkSumSize, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] checkSum); } #pragma warning restore 1591 [ComVisible(true), ComImport, Guid("FC073774-1739-4232-BD56-A027294BEC15"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ISymUnmanagedAsyncMethodPropertiesWriter { void DefineKickoffMethod([In] uint kickoffMethod); void DefineCatchHandlerILOffset([In] uint catchHandlerOffset); void DefineAsyncStepInfo([In] uint count, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] yieldOffsets, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] breakpointOffset, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] uint[] breakpointMethod); } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/ImageStreamIStream.cs000066400000000000000000000107451325033663500226300ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using dnlib.IO; namespace dnlib.DotNet.Pdb.Dss { /// /// Implements and uses an as the underlying /// stream. /// sealed class ImageStreamIStream : IStream, IDisposable { readonly IImageStream stream; readonly string name; const int STG_E_INVALIDFUNCTION = unchecked((int)0x80030001); const int STG_E_CANTSAVE = unchecked((int)0x80030103); /// /// User can set this to anything he/she wants. If it implements , /// its method will get called when this instance /// is 'd. /// public object UserData { get; set; } /// /// Constructor /// /// Source stream public ImageStreamIStream(IImageStream stream) : this(stream, string.Empty) { } /// /// Constructor /// /// Source stream /// Name of original file or null if unknown. public ImageStreamIStream(IImageStream stream, string name) { if (stream == null) throw new ArgumentNullException("stream"); this.stream = stream; this.name = name ?? string.Empty; } /// public void Clone(out IStream ppstm) { var newStream = stream.Clone(); newStream.Position = stream.Position; ppstm = new ImageStreamIStream(newStream, name); } /// public void Commit(int grfCommitFlags) { } /// public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten) { if (cb > int.MaxValue) cb = int.MaxValue; else if (cb < 0) cb = 0; int sizeToRead = (int)cb; if (stream.Position + sizeToRead < sizeToRead || stream.Position + sizeToRead > stream.Length) sizeToRead = (int)(stream.Length - Math.Min(stream.Position, stream.Length)); var buffer = new byte[sizeToRead]; Read(buffer, sizeToRead, pcbRead); if (pcbRead != IntPtr.Zero) Marshal.WriteInt64(pcbRead, Marshal.ReadInt32(pcbRead)); pstm.Write(buffer, buffer.Length, pcbWritten); if (pcbWritten != IntPtr.Zero) Marshal.WriteInt64(pcbWritten, Marshal.ReadInt32(pcbWritten)); } /// public void LockRegion(long libOffset, long cb, int dwLockType) { Marshal.ThrowExceptionForHR(STG_E_INVALIDFUNCTION); } /// public void Read(byte[] pv, int cb, IntPtr pcbRead) { if (cb < 0) cb = 0; cb = stream.Read(pv, 0, cb); if (pcbRead != IntPtr.Zero) Marshal.WriteInt32(pcbRead, cb); } /// public void Revert() { } enum STREAM_SEEK { SET = 0, CUR = 1, END = 2, } /// public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition) { switch ((STREAM_SEEK)dwOrigin) { case STREAM_SEEK.SET: stream.Position = dlibMove; break; case STREAM_SEEK.CUR: stream.Position += dlibMove; break; case STREAM_SEEK.END: stream.Position = stream.Length + dlibMove; break; } if (plibNewPosition != IntPtr.Zero) Marshal.WriteInt64(plibNewPosition, stream.Position); } /// public void SetSize(long libNewSize) { Marshal.ThrowExceptionForHR(STG_E_INVALIDFUNCTION); } enum STATFLAG { DEFAULT = 0, NONAME = 1, NOOPEN = 2, } enum STGTY { STORAGE = 1, STREAM = 2, LOCKBYTES = 3, PROPERTY = 4, } /// public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag) { var s = new System.Runtime.InteropServices.ComTypes.STATSTG(); // s.atime = ???; s.cbSize = stream.Length; s.clsid = Guid.Empty; // s.ctime = ???; s.grfLocksSupported = 0; s.grfMode = 0; s.grfStateBits = 0; // s.mtime = ???; if ((grfStatFlag & (int)STATFLAG.NONAME) == 0) s.pwcsName = name; s.reserved = 0; s.type = (int)STGTY.STREAM; pstatstg = s; } /// public void UnlockRegion(long libOffset, long cb, int dwLockType) { Marshal.ThrowExceptionForHR(STG_E_INVALIDFUNCTION); } /// public void Write(byte[] pv, int cb, IntPtr pcbWritten) { Marshal.ThrowExceptionForHR(STG_E_CANTSAVE); } /// public void Dispose() { stream.Dispose(); var id = UserData as IDisposable; if (id != null) id.Dispose(); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/MDEmitter.cs000066400000000000000000000510461325033663500207760ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Runtime.InteropServices.ComTypes; using dnlib.DotNet.Writer; namespace dnlib.DotNet.Pdb.Dss { /// /// Pass this instance to when writing the PDB file /// sealed class MDEmitter : IMetaDataImport, IMetaDataEmit { readonly MetaData metaData; readonly Dictionary tokenToTypeDef; readonly Dictionary tokenToMethodDef; /// /// Constructor /// /// Metadata public MDEmitter(MetaData metaData) { this.metaData = metaData; // We could get these from the metadata tables but it's just easier to get name, // declaring type etc using TypeDef and MethodDef. tokenToTypeDef = new Dictionary(metaData.TablesHeap.TypeDefTable.Rows); tokenToMethodDef = new Dictionary(metaData.TablesHeap.MethodTable.Rows); foreach (var type in metaData.Module.GetTypes()) { if (type == null) continue; tokenToTypeDef.Add(new MDToken(MD.Table.TypeDef, metaData.GetRid(type)).Raw, type); foreach (var method in type.Methods) { if (method == null) continue; tokenToMethodDef.Add(new MDToken(MD.Table.Method, metaData.GetRid(method)).Raw, method); } } } unsafe void IMetaDataImport.GetMethodProps(uint mb, uint* pClass, ushort* szMethod, uint cchMethod, uint* pchMethod, uint* pdwAttr, IntPtr* ppvSigBlob, uint* pcbSigBlob, uint* pulCodeRVA, uint* pdwImplFlags) { if ((mb >> 24) != 0x06) throw new ArgumentException(); var method = tokenToMethodDef[mb]; var row = metaData.TablesHeap.MethodTable[mb & 0x00FFFFFF]; if (pClass != null) *pClass = new MDToken(MD.Table.TypeDef, metaData.GetRid(method.DeclaringType)).Raw; if (pdwAttr != null) *pdwAttr = row.Flags; if (ppvSigBlob != null) *ppvSigBlob = IntPtr.Zero; if (pcbSigBlob != null) *pcbSigBlob = 0; if (pulCodeRVA != null) *pulCodeRVA = row.RVA; if (pdwImplFlags != null) *pdwImplFlags = row.ImplFlags; string name = method.Name.String ?? string.Empty; int len = (int)Math.Min((uint)name.Length + 1, cchMethod); if (szMethod != null) { for (int i = 0; i < len - 1; i++, szMethod++) *szMethod = (ushort)name[i]; if (len > 0) *szMethod = 0; } if (pchMethod != null) *pchMethod = (uint)len; } unsafe void IMetaDataImport.GetTypeDefProps(uint td, ushort* szTypeDef, uint cchTypeDef, uint* pchTypeDef, uint* pdwTypeDefFlags, uint* ptkExtends) { if ((td >> 24) != 0x02) throw new ArgumentException(); var type = tokenToTypeDef[td]; var row = metaData.TablesHeap.TypeDefTable[td & 0x00FFFFFF]; if (pdwTypeDefFlags != null) *pdwTypeDefFlags = row.Flags; if (ptkExtends != null) *ptkExtends = row.Extends; string name = type.Name.String ?? string.Empty; int len = (int)Math.Min((uint)name.Length + 1, cchTypeDef); if (szTypeDef != null) { for (int i = 0; i < len - 1; i++, szTypeDef++) *szTypeDef = (ushort)name[i]; if (len > 0) *szTypeDef = 0; } if (pchTypeDef != null) *pchTypeDef = (uint)len; } unsafe void IMetaDataImport.GetNestedClassProps(uint tdNestedClass, uint* ptdEnclosingClass) { if ((tdNestedClass >> 24) != 0x02) throw new ArgumentException(); var type = tokenToTypeDef[tdNestedClass]; var declType = type.DeclaringType; if (ptdEnclosingClass != null) { if (declType == null) *ptdEnclosingClass = 0; else *ptdEnclosingClass = new MDToken(MD.Table.TypeDef, metaData.GetRid(declType)).Raw; } } // The rest of the methods aren't called void IMetaDataImport.CloseEnum(IntPtr hEnum) { throw new NotImplementedException(); } void IMetaDataImport.CountEnum(IntPtr hEnum, ref uint pulCount) { throw new NotImplementedException(); } void IMetaDataImport.ResetEnum(IntPtr hEnum, uint ulPos) { throw new NotImplementedException(); } void IMetaDataImport.EnumTypeDefs(IntPtr phEnum, uint[] rTypeDefs, uint cMax, out uint pcTypeDefs) { throw new NotImplementedException(); } void IMetaDataImport.EnumInterfaceImpls(ref IntPtr phEnum, uint td, uint[] rImpls, uint cMax, ref uint pcImpls) { throw new NotImplementedException(); } void IMetaDataImport.EnumTypeRefs(ref IntPtr phEnum, uint[] rTypeRefs, uint cMax, ref uint pcTypeRefs) { throw new NotImplementedException(); } void IMetaDataImport.FindTypeDefByName(string szTypeDef, uint tkEnclosingClass, out uint ptd) { throw new NotImplementedException(); } void IMetaDataImport.GetScopeProps(IntPtr szName, uint cchName, out uint pchName, out Guid pmvid) { throw new NotImplementedException(); } void IMetaDataImport.GetModuleFromScope(out uint pmd) { throw new NotImplementedException(); } void IMetaDataImport.GetInterfaceImplProps(uint iiImpl, out uint pClass, out uint ptkIface) { throw new NotImplementedException(); } void IMetaDataImport.GetTypeRefProps(uint tr, out uint ptkResolutionScope, IntPtr szName, uint cchName, out uint pchName) { throw new NotImplementedException(); } void IMetaDataImport.ResolveTypeRef(uint tr, ref Guid riid, out object ppIScope, out uint ptd) { throw new NotImplementedException(); } void IMetaDataImport.EnumMembers(ref IntPtr phEnum, uint cl, uint[] rMembers, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumMembersWithName(ref IntPtr phEnum, uint cl, string szName, uint[] rMembers, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumMethods(ref IntPtr phEnum, uint cl, uint[] rMethods, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumMethodsWithName(ref IntPtr phEnum, uint cl, string szName, uint[] rMethods, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumFields(ref IntPtr phEnum, uint cl, uint[] rFields, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumFieldsWithName(ref IntPtr phEnum, uint cl, string szName, uint[] rFields, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumParams(ref IntPtr phEnum, uint mb, uint[] rParams, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumMemberRefs(ref IntPtr phEnum, uint tkParent, uint[] rMemberRefs, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumMethodImpls(ref IntPtr phEnum, uint td, uint[] rMethodBody, uint[] rMethodDecl, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.EnumPermissionSets(ref IntPtr phEnum, uint tk, uint dwActions, uint[] rPermission, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.FindMember(uint td, string szName, IntPtr pvSigBlob, uint cbSigBlob, out uint pmb) { throw new NotImplementedException(); } void IMetaDataImport.FindMethod(uint td, string szName, IntPtr pvSigBlob, uint cbSigBlob, out uint pmb) { throw new NotImplementedException(); } void IMetaDataImport.FindField(uint td, string szName, IntPtr pvSigBlob, uint cbSigBlob, out uint pmb) { throw new NotImplementedException(); } void IMetaDataImport.FindMemberRef(uint td, string szName, IntPtr pvSigBlob, uint cbSigBlob, out uint pmr) { throw new NotImplementedException(); } void IMetaDataImport.GetMemberRefProps(uint mr, out uint ptk, IntPtr szMember, uint cchMember, out uint pchMember, out IntPtr ppvSigBlob, out uint pbSig) { throw new NotImplementedException(); } void IMetaDataImport.EnumProperties(ref IntPtr phEnum, uint td, uint[] rProperties, uint cMax, out uint pcProperties) { throw new NotImplementedException(); } void IMetaDataImport.EnumEvents(ref IntPtr phEnum, uint td, uint[] rEvents, uint cMax, out uint pcEvents) { throw new NotImplementedException(); } void IMetaDataImport.GetEventProps(uint ev, out uint pClass, string szEvent, uint cchEvent, out uint pchEvent, out uint pdwEventFlags, out uint ptkEventType, out uint pmdAddOn, out uint pmdRemoveOn, out uint pmdFire, uint[] rmdOtherMethod, uint cMax, out uint pcOtherMethod) { throw new NotImplementedException(); } void IMetaDataImport.EnumMethodSemantics(ref IntPtr phEnum, uint mb, uint[] rEventProp, uint cMax, out uint pcEventProp) { throw new NotImplementedException(); } void IMetaDataImport.GetMethodSemantics(uint mb, uint tkEventProp, out uint pdwSemanticsFlags) { throw new NotImplementedException(); } void IMetaDataImport.GetClassLayout(uint td, out uint pdwPackSize, out IntPtr rFieldOffset, uint cMax, out uint pcFieldOffset, out uint pulClassSize) { throw new NotImplementedException(); } void IMetaDataImport.GetFieldMarshal(uint tk, out IntPtr ppvNativeType, out uint pcbNativeType) { throw new NotImplementedException(); } void IMetaDataImport.GetRVA(uint tk, out uint pulCodeRVA, out uint pdwImplFlags) { throw new NotImplementedException(); } void IMetaDataImport.GetPermissionSetProps(uint pm, out uint pdwAction, out IntPtr ppvPermission, out uint pcbPermission) { throw new NotImplementedException(); } void IMetaDataImport.GetSigFromToken(uint mdSig, out IntPtr ppvSig, out uint pcbSig) { throw new NotImplementedException(); } void IMetaDataImport.GetModuleRefProps(uint mur, IntPtr szName, uint cchName, out uint pchName) { throw new NotImplementedException(); } void IMetaDataImport.EnumModuleRefs(ref IntPtr phEnum, uint[] rModuleRefs, uint cmax, out uint pcModuleRefs) { throw new NotImplementedException(); } void IMetaDataImport.GetTypeSpecFromToken(uint typespec, out IntPtr ppvSig, out uint pcbSig) { throw new NotImplementedException(); } void IMetaDataImport.GetNameFromToken(uint tk, out IntPtr pszUtf8NamePtr) { throw new NotImplementedException(); } void IMetaDataImport.EnumUnresolvedMethods(ref IntPtr phEnum, uint[] rMethods, uint cMax, out uint pcTokens) { throw new NotImplementedException(); } void IMetaDataImport.GetUserString(uint stk, IntPtr szString, uint cchString, out uint pchString) { throw new NotImplementedException(); } void IMetaDataImport.GetPinvokeMap(uint tk, out uint pdwMappingFlags, IntPtr szImportName, uint cchImportName, out uint pchImportName, out uint pmrImportDLL) { throw new NotImplementedException(); } void IMetaDataImport.EnumSignatures(ref IntPtr phEnum, uint[] rSignatures, uint cmax, out uint pcSignatures) { throw new NotImplementedException(); } void IMetaDataImport.EnumTypeSpecs(ref IntPtr phEnum, uint[] rTypeSpecs, uint cmax, out uint pcTypeSpecs) { throw new NotImplementedException(); } void IMetaDataImport.EnumUserStrings(ref IntPtr phEnum, uint[] rStrings, uint cmax, out uint pcStrings) { throw new NotImplementedException(); } void IMetaDataImport.GetParamForMethodIndex(uint md, uint ulParamSeq, out uint ppd) { throw new NotImplementedException(); } void IMetaDataImport.EnumCustomAttributes(IntPtr phEnum, uint tk, uint tkType, uint[] rCustomAttributes, uint cMax, out uint pcCustomAttributes) { throw new NotImplementedException(); } void IMetaDataImport.GetCustomAttributeProps(uint cv, out uint ptkObj, out uint ptkType, out IntPtr ppBlob, out uint pcbSize) { throw new NotImplementedException(); } void IMetaDataImport.FindTypeRef(uint tkResolutionScope, string szName, out uint ptr) { throw new NotImplementedException(); } void IMetaDataImport.GetMemberProps(uint mb, out uint pClass, IntPtr szMember, uint cchMember, out uint pchMember, out uint pdwAttr, out IntPtr ppvSigBlob, out uint pcbSigBlob, out uint pulCodeRVA, out uint pdwImplFlags, out uint pdwCPlusTypeFlag, out IntPtr ppValue, out uint pcchValue) { throw new NotImplementedException(); } void IMetaDataImport.GetFieldProps(uint mb, out uint pClass, IntPtr szField, uint cchField, out uint pchField, out uint pdwAttr, out IntPtr ppvSigBlob, out uint pcbSigBlob, out uint pdwCPlusTypeFlag, out IntPtr ppValue, out uint pcchValue) { throw new NotImplementedException(); } void IMetaDataImport.GetPropertyProps(uint prop, out uint pClass, IntPtr szProperty, uint cchProperty, out uint pchProperty, out uint pdwPropFlags, out IntPtr ppvSig, out uint pbSig, out uint pdwCPlusTypeFlag, out IntPtr ppDefaultValue, out uint pcchDefaultValue, out uint pmdSetter, out uint pmdGetter, uint[] rmdOtherMethod, uint cMax, out uint pcOtherMethod) { throw new NotImplementedException(); } void IMetaDataImport.GetParamProps(uint tk, out uint pmd, out uint pulSequence, IntPtr szName, uint cchName, out uint pchName, out uint pdwAttr, out uint pdwCPlusTypeFlag, out IntPtr ppValue, out uint pcchValue) { throw new NotImplementedException(); } void IMetaDataImport.GetCustomAttributeByName(uint tkObj, string szName, out IntPtr ppData, out uint pcbData) { throw new NotImplementedException(); } bool IMetaDataImport.IsValidToken(uint tk) { throw new NotImplementedException(); } void IMetaDataImport.GetNativeCallConvFromSig(IntPtr pvSig, uint cbSig, out uint pCallConv) { throw new NotImplementedException(); } void IMetaDataImport.IsGlobal(uint pd, out int pbGlobal) { throw new NotImplementedException(); } void IMetaDataEmit.SetModuleProps(string szName) { throw new NotImplementedException(); } void IMetaDataEmit.Save(string szFile, uint dwSaveFlags) { throw new NotImplementedException(); } void IMetaDataEmit.SaveToStream(IStream pIStream, uint dwSaveFlags) { throw new NotImplementedException(); } void IMetaDataEmit.GetSaveSize(int fSave, out uint pdwSaveSize) { throw new NotImplementedException(); } void IMetaDataEmit.DefineTypeDef(string szTypeDef, uint dwTypeDefFlags, uint tkExtends, uint[] rtkImplements, out uint ptd) { throw new NotImplementedException(); } void IMetaDataEmit.DefineNestedType(string szTypeDef, uint dwTypeDefFlags, uint tkExtends, uint[] rtkImplements, uint tdEncloser, out uint ptd) { throw new NotImplementedException(); } void IMetaDataEmit.SetHandler(object pUnk) { throw new NotImplementedException(); } void IMetaDataEmit.DefineMethod(uint td, string szName, uint dwMethodFlags, IntPtr pvSigBlob, uint cbSigBlob, uint ulCodeRVA, uint dwImplFlags, out uint pmd) { throw new NotImplementedException(); } void IMetaDataEmit.DefineMethodImpl(uint td, uint tkBody, uint tkDecl) { throw new NotImplementedException(); } void IMetaDataEmit.DefineTypeRefByName(uint tkResolutionScope, string szName, out uint ptr) { throw new NotImplementedException(); } void IMetaDataEmit.DefineImportType(IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport pImport, uint tdImport, IntPtr pAssemEmit, out uint ptr) { throw new NotImplementedException(); } void IMetaDataEmit.DefineMemberRef(uint tkImport, string szName, IntPtr pvSigBlob, uint cbSigBlob, out uint pmr) { throw new NotImplementedException(); } void IMetaDataEmit.DefineImportMember(IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport pImport, uint mbMember, IntPtr pAssemEmit, uint tkParent, out uint pmr) { throw new NotImplementedException(); } void IMetaDataEmit.DefineEvent(uint td, string szEvent, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, uint[] rmdOtherMethods, out uint pmdEvent) { throw new NotImplementedException(); } void IMetaDataEmit.SetClassLayout(uint td, uint dwPackSize, IntPtr rFieldOffsets, uint ulClassSize) { throw new NotImplementedException(); } void IMetaDataEmit.DeleteClassLayout(uint td) { throw new NotImplementedException(); } void IMetaDataEmit.SetFieldMarshal(uint tk, IntPtr pvNativeType, uint cbNativeType) { throw new NotImplementedException(); } void IMetaDataEmit.DeleteFieldMarshal(uint tk) { throw new NotImplementedException(); } void IMetaDataEmit.DefinePermissionSet(uint tk, uint dwAction, IntPtr pvPermission, uint cbPermission, out uint ppm) { throw new NotImplementedException(); } void IMetaDataEmit.SetRVA(uint md, uint ulRVA) { throw new NotImplementedException(); } void IMetaDataEmit.GetTokenFromSig(IntPtr pvSig, uint cbSig, out uint pmsig) { throw new NotImplementedException(); } void IMetaDataEmit.DefineModuleRef(string szName, out uint pmur) { throw new NotImplementedException(); } void IMetaDataEmit.SetParent(uint mr, uint tk) { throw new NotImplementedException(); } void IMetaDataEmit.GetTokenFromTypeSpec(IntPtr pvSig, uint cbSig, out uint ptypespec) { throw new NotImplementedException(); } void IMetaDataEmit.SaveToMemory(out IntPtr pbData, uint cbData) { throw new NotImplementedException(); } void IMetaDataEmit.DefineUserString(string szString, uint cchString, out uint pstk) { throw new NotImplementedException(); } void IMetaDataEmit.DeleteToken(uint tkObj) { throw new NotImplementedException(); } void IMetaDataEmit.SetMethodProps(uint md, uint dwMethodFlags, uint ulCodeRVA, uint dwImplFlags) { throw new NotImplementedException(); } void IMetaDataEmit.SetTypeDefProps(uint td, uint dwTypeDefFlags, uint tkExtends, uint[] rtkImplements) { throw new NotImplementedException(); } void IMetaDataEmit.SetEventProps(uint ev, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, uint[] rmdOtherMethods) { throw new NotImplementedException(); } void IMetaDataEmit.SetPermissionSetProps(uint tk, uint dwAction, IntPtr pvPermission, uint cbPermission, out uint ppm) { throw new NotImplementedException(); } void IMetaDataEmit.DefinePinvokeMap(uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL) { throw new NotImplementedException(); } void IMetaDataEmit.SetPinvokeMap(uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL) { throw new NotImplementedException(); } void IMetaDataEmit.DeletePinvokeMap(uint tk) { throw new NotImplementedException(); } void IMetaDataEmit.DefineCustomAttribute(uint tkOwner, uint tkCtor, IntPtr pCustomAttribute, uint cbCustomAttribute, out uint pcv) { throw new NotImplementedException(); } void IMetaDataEmit.SetCustomAttributeValue(uint pcv, IntPtr pCustomAttribute, uint cbCustomAttribute) { throw new NotImplementedException(); } void IMetaDataEmit.DefineField(uint td, string szName, uint dwFieldFlags, IntPtr pvSigBlob, uint cbSigBlob, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, out uint pmd) { throw new NotImplementedException(); } void IMetaDataEmit.DefineProperty(uint td, string szProperty, uint dwPropFlags, IntPtr pvSig, uint cbSig, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, uint mdSetter, uint mdGetter, uint[] rmdOtherMethods, out uint pmdProp) { throw new NotImplementedException(); } void IMetaDataEmit.DefineParam(uint md, uint ulParamSeq, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, out uint ppd) { throw new NotImplementedException(); } void IMetaDataEmit.SetFieldProps(uint fd, uint dwFieldFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue) { throw new NotImplementedException(); } void IMetaDataEmit.SetPropertyProps(uint pr, uint dwPropFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, uint mdSetter, uint mdGetter, uint[] rmdOtherMethods) { throw new NotImplementedException(); } void IMetaDataEmit.SetParamProps(uint pd, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue) { throw new NotImplementedException(); } void IMetaDataEmit.DefineSecurityAttributeSet(uint tkObj, IntPtr rSecAttrs, uint cSecAttrs, out uint pulErrorAttr) { throw new NotImplementedException(); } void IMetaDataEmit.ApplyEditAndContinue(object pImport) { throw new NotImplementedException(); } void IMetaDataEmit.TranslateSigWithScope(IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport import, IntPtr pbSigBlob, uint cbSigBlob, IntPtr pAssemEmit, IMetaDataEmit emit, IntPtr pvTranslatedSig, uint cbTranslatedSigMax, out uint pcbTranslatedSig) { throw new NotImplementedException(); } void IMetaDataEmit.SetMethodImplFlags(uint md, uint dwImplFlags) { throw new NotImplementedException(); } void IMetaDataEmit.SetFieldRVA(uint fd, uint ulRVA) { throw new NotImplementedException(); } void IMetaDataEmit.Merge(IMetaDataImport pImport, IntPtr pHostMapToken, object pHandler) { throw new NotImplementedException(); } void IMetaDataEmit.MergeEnd() { throw new NotImplementedException(); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/PinnedMetaData.cs000066400000000000000000000034371325033663500217630ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Runtime.InteropServices; using dnlib.IO; namespace dnlib.DotNet.Pdb.Dss { /// /// Pins a metadata stream in memory /// sealed class PinnedMetaData : IDisposable { GCHandle gcHandle; readonly IImageStream stream; readonly byte[] streamData; readonly IntPtr address; /// /// Gets the address /// public IntPtr Address { get { return address; } } /// /// Gets the size /// public int Size { get { return (int)stream.Length; } } /// /// Constructor /// /// Metadata stream public PinnedMetaData(IImageStream stream) { this.stream = stream; var umStream = stream as UnmanagedMemoryImageStream; if (umStream != null) { this.address = umStream.StartAddress; GC.SuppressFinalize(this); // no GCHandle so finalizer isn't needed } else { var memStream = stream as MemoryImageStream; if (memStream != null) { this.streamData = memStream.DataArray; this.gcHandle = GCHandle.Alloc(this.streamData, GCHandleType.Pinned); this.address = new IntPtr(this.gcHandle.AddrOfPinnedObject().ToInt64() + memStream.DataOffset); } else { this.streamData = stream.ReadAllBytes(); this.gcHandle = GCHandle.Alloc(this.streamData, GCHandleType.Pinned); this.address = this.gcHandle.AddrOfPinnedObject(); } } } ~PinnedMetaData() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } void Dispose(bool disposing) { if (gcHandle.IsAllocated) { try { gcHandle.Free(); } catch (InvalidOperationException) { } } if (disposing) stream.Dispose(); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/StreamIStream.cs000066400000000000000000000076731325033663500216730ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; namespace dnlib.DotNet.Pdb.Dss { /// /// Implements and uses a as the underlying /// stream. /// sealed class StreamIStream : IStream { readonly Stream stream; readonly string name; const int STG_E_INVALIDFUNCTION = unchecked((int)0x80030001); /// /// Constructor /// /// Source stream public StreamIStream(Stream stream) : this(stream, string.Empty) { } /// /// Constructor /// /// Source stream /// Name of original file or null if unknown. public StreamIStream(Stream stream, string name) { if (stream == null) throw new ArgumentNullException("stream"); this.stream = stream; this.name = name ?? string.Empty; } /// public void Clone(out IStream ppstm) { Marshal.ThrowExceptionForHR(STG_E_INVALIDFUNCTION); throw new Exception(); } /// public void Commit(int grfCommitFlags) { stream.Flush(); } /// public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten) { if (cb > int.MaxValue) cb = int.MaxValue; else if (cb < 0) cb = 0; int sizeToRead = (int)cb; if (stream.Position + sizeToRead < sizeToRead || stream.Position + sizeToRead > stream.Length) sizeToRead = (int)(stream.Length - Math.Min(stream.Position, stream.Length)); var buffer = new byte[sizeToRead]; Read(buffer, sizeToRead, pcbRead); if (pcbRead != IntPtr.Zero) Marshal.WriteInt64(pcbRead, Marshal.ReadInt32(pcbRead)); pstm.Write(buffer, buffer.Length, pcbWritten); if (pcbWritten != IntPtr.Zero) Marshal.WriteInt64(pcbWritten, Marshal.ReadInt32(pcbWritten)); } /// public void LockRegion(long libOffset, long cb, int dwLockType) { Marshal.ThrowExceptionForHR(STG_E_INVALIDFUNCTION); } /// public void Read(byte[] pv, int cb, IntPtr pcbRead) { if (cb < 0) cb = 0; cb = stream.Read(pv, 0, cb); if (pcbRead != IntPtr.Zero) Marshal.WriteInt32(pcbRead, cb); } /// public void Revert() { } enum STREAM_SEEK { SET = 0, CUR = 1, END = 2, } /// public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition) { switch ((STREAM_SEEK)dwOrigin) { case STREAM_SEEK.SET: stream.Position = dlibMove; break; case STREAM_SEEK.CUR: stream.Position += dlibMove; break; case STREAM_SEEK.END: stream.Position = stream.Length + dlibMove; break; } if (plibNewPosition != IntPtr.Zero) Marshal.WriteInt64(plibNewPosition, stream.Position); } /// public void SetSize(long libNewSize) { stream.SetLength(libNewSize); } enum STATFLAG { DEFAULT = 0, NONAME = 1, NOOPEN = 2, } enum STGTY { STORAGE = 1, STREAM = 2, LOCKBYTES = 3, PROPERTY = 4, } /// public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag) { var s = new System.Runtime.InteropServices.ComTypes.STATSTG(); // s.atime = ???; s.cbSize = stream.Length; s.clsid = Guid.Empty; // s.ctime = ???; s.grfLocksSupported = 0; s.grfMode = 2; s.grfStateBits = 0; // s.mtime = ???; if ((grfStatFlag & (int)STATFLAG.NONAME) == 0) s.pwcsName = name; s.reserved = 0; s.type = (int)STGTY.STREAM; pstatstg = s; } /// public void UnlockRegion(long libOffset, long cb, int dwLockType) { Marshal.ThrowExceptionForHR(STG_E_INVALIDFUNCTION); } /// public void Write(byte[] pv, int cb, IntPtr pcbWritten) { stream.Write(pv, 0, cb); if (pcbWritten != IntPtr.Zero) Marshal.WriteInt32(pcbWritten, cb); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/SymbolDocumentImpl.cs000066400000000000000000000032201325033663500227210ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet.Pdb.Dss { sealed class SymbolDocumentImpl : SymbolDocument { readonly ISymUnmanagedDocument document; public ISymUnmanagedDocument SymUnmanagedDocument { get { return document; } } public SymbolDocumentImpl(ISymUnmanagedDocument document) { this.document = document; } public override Guid CheckSumAlgorithmId { get { Guid guid; document.GetCheckSumAlgorithmId(out guid); return guid; } } public override Guid DocumentType { get { Guid guid; document.GetDocumentType(out guid); return guid; } } public override Guid Language { get { Guid guid; document.GetLanguage(out guid); return guid; } } public override Guid LanguageVendor { get { Guid guid; document.GetLanguageVendor(out guid); return guid; } } public override string URL { get { uint count; document.GetURL(0, out count, null); var chars = new char[count]; document.GetURL((uint)chars.Length, out count, chars); if (chars.Length == 0) return string.Empty; return new string(chars, 0, chars.Length - 1); } } public override byte[] CheckSum { get { uint bufSize; document.GetCheckSum(0, out bufSize, null); var buffer = new byte[bufSize]; document.GetCheckSum((uint)buffer.Length, out bufSize, buffer); return buffer; } } public override PdbCustomDebugInfo[] CustomDebugInfos { get { return emptyPdbCustomDebugInfos; } } static readonly PdbCustomDebugInfo[] emptyPdbCustomDebugInfos = new PdbCustomDebugInfo[0]; } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/SymbolDocumentWriter.cs000066400000000000000000000012701325033663500232770ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics.SymbolStore; namespace dnlib.DotNet.Pdb.Dss { sealed class SymbolDocumentWriter : ISymbolDocumentWriter { readonly ISymUnmanagedDocumentWriter writer; public ISymUnmanagedDocumentWriter SymUnmanagedDocumentWriter { get { return writer; } } public SymbolDocumentWriter(ISymUnmanagedDocumentWriter writer) { this.writer = writer; } public void SetCheckSum(Guid algorithmId, byte[] checkSum) { writer.SetCheckSum(algorithmId, (uint)(checkSum == null ? 0 : checkSum.Length), checkSum); } public void SetSource(byte[] source) { writer.SetSource((uint)source.Length, source); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/SymbolMethodImpl.cs000066400000000000000000000072321325033663500223720ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Diagnostics.SymbolStore; using System.Threading; using dnlib.DotNet.Emit; using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet.Pdb.Dss { sealed class SymbolMethodImpl : SymbolMethod { readonly SymbolReaderImpl reader; readonly ISymUnmanagedMethod method; readonly ISymUnmanagedAsyncMethod asyncMethod; public SymbolMethodImpl(SymbolReaderImpl reader, ISymUnmanagedMethod method) { this.reader = reader; this.method = method; asyncMethod = method as ISymUnmanagedAsyncMethod; } public override int Token { get { uint result; method.GetToken(out result); return (int)result; } } public override SymbolScope RootScope { get { if (rootScope == null) { ISymUnmanagedScope scope; method.GetRootScope(out scope); Interlocked.CompareExchange(ref rootScope, scope == null ? null : new SymbolScopeImpl(scope, this, null), null); } return rootScope; } } volatile SymbolScope rootScope; public override IList SequencePoints { get { if (sequencePoints == null) { uint seqPointCount; method.GetSequencePointCount(out seqPointCount); var seqPoints = new SymbolSequencePoint[seqPointCount]; int[] offsets = new int[seqPoints.Length]; ISymbolDocument[] documents = new ISymbolDocument[seqPoints.Length]; int[] lines = new int[seqPoints.Length]; int[] columns = new int[seqPoints.Length]; int[] endLines = new int[seqPoints.Length]; int[] endColumns = new int[seqPoints.Length]; var unDocs = new ISymUnmanagedDocument[seqPoints.Length]; if (seqPoints.Length != 0) { uint size; method.GetSequencePoints((uint)seqPoints.Length, out size, offsets, unDocs, lines, columns, endLines, endColumns); } for (int i = 0; i < seqPoints.Length; i++) { seqPoints[i] = new SymbolSequencePoint { Offset = offsets[i], Document = new SymbolDocumentImpl(unDocs[i]), Line = lines[i], Column = columns[i], EndLine = endLines[i], EndColumn = endColumns[i], }; } sequencePoints = seqPoints; } return sequencePoints; } } volatile SymbolSequencePoint[] sequencePoints; public int AsyncKickoffMethod { get { if (asyncMethod == null || !asyncMethod.IsAsyncMethod()) return 0; return (int)asyncMethod.GetKickoffMethod(); } } public uint? AsyncCatchHandlerILOffset { get { if (asyncMethod == null || !asyncMethod.IsAsyncMethod()) return null; if (!asyncMethod.HasCatchHandlerILOffset()) return null; return asyncMethod.GetCatchHandlerILOffset(); } } public IList AsyncStepInfos { get { if (asyncMethod == null || !asyncMethod.IsAsyncMethod()) return null; if (asyncStepInfos == null) { var stepInfoCount = asyncMethod.GetAsyncStepInfoCount(); var yieldOffsets = new uint[stepInfoCount]; var breakpointOffsets = new uint[stepInfoCount]; var breakpointMethods = new uint[stepInfoCount]; asyncMethod.GetAsyncStepInfo(stepInfoCount, out stepInfoCount, yieldOffsets, breakpointOffsets, breakpointMethods); var res = new SymbolAsyncStepInfo[stepInfoCount]; for (int i = 0; i < res.Length; i++) res[i] = new SymbolAsyncStepInfo(yieldOffsets[i], breakpointOffsets[i], breakpointMethods[i]); asyncStepInfos = res; } return asyncStepInfos; } } volatile SymbolAsyncStepInfo[] asyncStepInfos; public override void GetCustomDebugInfos(MethodDef method, CilBody body, IList result) { reader.GetCustomDebugInfos(this, method, body, result); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/SymbolNamespaceImpl.cs000066400000000000000000000011251325033663500230410ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet.Pdb.Dss { sealed class SymbolNamespaceImpl : SymbolNamespace { readonly ISymUnmanagedNamespace ns; public SymbolNamespaceImpl(ISymUnmanagedNamespace @namespace) { this.ns = @namespace; } public override string Name { get { uint count; ns.GetName(0, out count, null); var chars = new char[count]; ns.GetName((uint)chars.Length, out count, chars); if (chars.Length == 0) return string.Empty; return new string(chars, 0, chars.Length - 1); } } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/SymbolReaderCreator.cs000066400000000000000000000200651325033663500230510ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using System.Runtime.InteropServices; using System.Security; using dnlib.DotNet.MD; using dnlib.IO; using dnlib.PE; using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet.Pdb.Dss { /// /// Creates a instance /// static class SymbolReaderCreator { [DllImport("ole32")] static extern int CoCreateInstance([In] ref Guid rclsid, IntPtr pUnkOuter, [In] uint dwClsContext, [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.IUnknown)] out object ppv); static readonly Guid CLSID_CorSymBinder_SxS = new Guid(0x0A29FF9E, 0x7F9C, 0x4437, 0x8B, 0x11, 0xF4, 0x24, 0x49, 0x1E, 0x39, 0x31); /// /// Creates a new instance /// /// Path to assembly /// A new instance or null if there's no PDB /// file on disk or if any of the COM methods fail. public static SymbolReader CreateFromAssemblyFile(string assemblyFileName) { try { object mdDispObj; Guid CLSID_CorMetaDataDispenser = new Guid(0xE5CB7A31, 0x7512, 0x11D2, 0x89, 0xCE, 0x0, 0x80, 0xC7, 0x92, 0xE5, 0xD8); Guid IID_IMetaDataDispenser = new Guid(0x809C652E, 0x7396, 0x11D2, 0x97, 0x71, 0x00, 0xA0, 0xC9, 0xB4, 0xD5, 0x0C); int hr = CoCreateInstance(ref CLSID_CorMetaDataDispenser, IntPtr.Zero, 1, ref IID_IMetaDataDispenser, out mdDispObj); if (hr < 0) return null; object mdImportObj; var mdDisp = (IMetaDataDispenser)mdDispObj; Guid IID_IMetaDataImport = new Guid(0x7DAC8207, 0xD3AE, 0x4C75, 0x9B, 0x67, 0x92, 0x80, 0x1A, 0x49, 0x7D, 0x44); mdDisp.OpenScope(assemblyFileName, 0, ref IID_IMetaDataImport, out mdImportObj); Marshal.FinalReleaseComObject(mdDispObj); ISymUnmanagedReader symReader; var binder = (ISymUnmanagedBinder)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_CorSymBinder_SxS)); hr = binder.GetReaderForFile((IMetaDataImport)mdImportObj, assemblyFileName, null, out symReader); Marshal.FinalReleaseComObject(mdImportObj); Marshal.FinalReleaseComObject(binder); if (hr >= 0) return new SymbolReaderImpl(symReader); } catch (IOException) { } catch (UnauthorizedAccessException) { } catch (SecurityException) { } catch (InvalidCastException) { } catch (COMException) { } return null; } /// /// Creates a new instance /// /// .NET metadata /// Path to PDB file /// A new instance or null if there's no PDB /// file on disk or if any of the COM methods fail. public static SymbolReader Create(IMetaData metaData, string pdbFileName) { var mdStream = CreateMetaDataStream(metaData); try { return Create(mdStream, ImageStreamUtils.OpenImageStream(pdbFileName)); } catch { if (mdStream != null) mdStream.Dispose(); throw; } } /// /// Creates a new instance /// /// .NET metadata /// PDB file data /// A new instance or null if any of the COM /// methods fail. public static SymbolReader Create(IMetaData metaData, byte[] pdbData) { if (pdbData == null) return null; var mdStream = CreateMetaDataStream(metaData); try { return Create(mdStream, MemoryImageStream.Create(pdbData)); } catch { if (mdStream != null) mdStream.Dispose(); throw; } } /// /// Creates a new instance /// /// .NET metadata /// PDB file stream which is now owned by this method /// A new instance or null if any of the COM /// methods fail. public static SymbolReader Create(IMetaData metaData, IImageStream pdbStream) { try { return Create(CreateMetaDataStream(metaData), pdbStream); } catch { if (pdbStream != null) pdbStream.Dispose(); throw; } } /// /// Creates a new instance /// /// .NET metadata stream which is now owned by this method /// Path to PDB file /// A new instance or null if there's no PDB /// file on disk or if any of the COM methods fail. public static SymbolReader Create(IImageStream mdStream, string pdbFileName) { try { return Create(mdStream, ImageStreamUtils.OpenImageStream(pdbFileName)); } catch { if (mdStream != null) mdStream.Dispose(); throw; } } /// /// Creates a new instance /// /// .NET metadata stream which is now owned by this method /// PDB file data /// A new instance or null if any of the COM /// methods fail. public static SymbolReader Create(IImageStream mdStream, byte[] pdbData) { if (pdbData == null) { if (mdStream != null) mdStream.Dispose(); return null; } try { return Create(mdStream, MemoryImageStream.Create(pdbData)); } catch { if (mdStream != null) mdStream.Dispose(); throw; } } /// /// Creates a new instance /// /// .NET metadata stream which is now owned by this method /// PDB file stream which is now owned by this method /// A new instance or null if any of the COM /// methods fail. public static SymbolReader Create(IImageStream mdStream, IImageStream pdbStream) { ImageStreamIStream stream = null; PinnedMetaData pinnedMd = null; bool error = true; try { if (pdbStream == null || mdStream == null) return null; object mdDispObj; Guid CLSID_CorMetaDataDispenser = new Guid(0xE5CB7A31, 0x7512, 0x11D2, 0x89, 0xCE, 0x0, 0x80, 0xC7, 0x92, 0xE5, 0xD8); Guid IID_IMetaDataDispenser = new Guid(0x809C652E, 0x7396, 0x11D2, 0x97, 0x71, 0x00, 0xA0, 0xC9, 0xB4, 0xD5, 0x0C); int hr = CoCreateInstance(ref CLSID_CorMetaDataDispenser, IntPtr.Zero, 1, ref IID_IMetaDataDispenser, out mdDispObj); if (hr < 0) return null; object mdImportObj; var mdDisp = (IMetaDataDispenser)mdDispObj; Guid IID_IMetaDataImport = new Guid(0x7DAC8207, 0xD3AE, 0x4C75, 0x9B, 0x67, 0x92, 0x80, 0x1A, 0x49, 0x7D, 0x44); pinnedMd = new PinnedMetaData(mdStream); mdDisp.OpenScopeOnMemory(pinnedMd.Address, (uint)pinnedMd.Size, 0x10, ref IID_IMetaDataImport, out mdImportObj); Marshal.FinalReleaseComObject(mdDispObj); ISymUnmanagedReader symReader; var binder = (ISymUnmanagedBinder)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_CorSymBinder_SxS)); stream = new ImageStreamIStream(pdbStream, null) { UserData = pinnedMd }; hr = binder.GetReaderFromStream((IMetaDataImport)mdImportObj, stream, out symReader); Marshal.FinalReleaseComObject(mdImportObj); Marshal.FinalReleaseComObject(binder); if (hr >= 0) { error = false; return new SymbolReaderImpl(symReader); } } catch (IOException) { } catch (InvalidCastException) { } catch (COMException) { } finally { if (error) { if (stream != null) stream.Dispose(); if (pinnedMd != null) pinnedMd.Dispose(); if (mdStream != null) mdStream.Dispose(); if (pdbStream != null) pdbStream.Dispose(); } } return null; } static IImageStream CreateMetaDataStream(IMetaData metaData) { var peImage = metaData.PEImage; var mdDataDir = metaData.ImageCor20Header.MetaData; return peImage.CreateStream(mdDataDir.VirtualAddress, mdDataDir.Size); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/SymbolReaderImpl.cs000066400000000000000000000054171325033663500223570ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Runtime.InteropServices; using dnlib.DotNet.Emit; using dnlib.DotNet.Pdb.Symbols; using dnlib.DotNet.Pdb.WindowsPdb; namespace dnlib.DotNet.Pdb.Dss { sealed class SymbolReaderImpl : SymbolReader { ModuleDef module; readonly ISymUnmanagedReader reader; const int E_FAIL = unchecked((int)0x80004005); /// /// Constructor /// /// An unmanaged symbol reader public SymbolReaderImpl(ISymUnmanagedReader reader) { if (reader == null) throw new ArgumentNullException("reader"); this.reader = reader; } public override PdbFileKind PdbFileKind { get { return PdbFileKind.WindowsPDB; } } public override int UserEntryPoint { get { uint token; int hr = reader.GetUserEntryPoint(out token); if (hr == E_FAIL) token = 0; else Marshal.ThrowExceptionForHR(hr); return (int)token; } } public override IList Documents { get { if (documents == null) { uint numDocs; reader.GetDocuments(0, out numDocs, null); var unDocs = new ISymUnmanagedDocument[numDocs]; reader.GetDocuments((uint)unDocs.Length, out numDocs, unDocs); var docs = new SymbolDocument[numDocs]; for (uint i = 0; i < numDocs; i++) docs[i] = new SymbolDocumentImpl(unDocs[i]); documents = docs; } return documents; } } volatile SymbolDocument[] documents; public override void Initialize(ModuleDef module) { this.module = module; } public override SymbolMethod GetMethod(MethodDef method, int version) { ISymUnmanagedMethod unMethod; int hr = reader.GetMethodByVersion(method.MDToken.Raw, version, out unMethod); if (hr == E_FAIL) return null; Marshal.ThrowExceptionForHR(hr); return unMethod == null ? null : new SymbolMethodImpl(this, unMethod); } internal void GetCustomDebugInfos(SymbolMethodImpl symMethod, MethodDef method, CilBody body, IList result) { var asyncMethod = PseudoCustomDebugInfoFactory.TryCreateAsyncMethod(method.Module, method, body, symMethod.AsyncKickoffMethod, symMethod.AsyncStepInfos, symMethod.AsyncCatchHandlerILOffset); if (asyncMethod != null) result.Add(asyncMethod); const string CDI_NAME = "MD2"; uint bufSize; reader.GetSymAttribute(method.MDToken.Raw, CDI_NAME, 0, out bufSize, null); if (bufSize == 0) return; var cdiData = new byte[bufSize]; reader.GetSymAttribute(method.MDToken.Raw, CDI_NAME, (uint)cdiData.Length, out bufSize, cdiData); PdbCustomDebugInfoReader.Read(method, body, result, cdiData); } public override void GetCustomDebugInfos(int token, GenericParamContext gpContext, IList result) { } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/SymbolScopeImpl.cs000066400000000000000000000107051325033663500222220ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Diagnostics; using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet.Pdb.Dss { sealed class SymbolScopeImpl : SymbolScope { readonly ISymUnmanagedScope scope; readonly SymbolMethod method; readonly SymbolScope parent; public SymbolScopeImpl(ISymUnmanagedScope scope, SymbolMethod method, SymbolScope parent) { this.scope = scope; this.method = method; this.parent = parent; } public override SymbolMethod Method { get { return method; } } public override SymbolScope Parent { get { return parent; } } public override int StartOffset { get { uint result; scope.GetStartOffset(out result); return (int)result; } } public override int EndOffset { get { uint result; scope.GetEndOffset(out result); return (int)result; } } public override IList Children { get { if (children == null) { uint numScopes; scope.GetChildren(0, out numScopes, null); var unScopes = new ISymUnmanagedScope[numScopes]; scope.GetChildren((uint)unScopes.Length, out numScopes, unScopes); var scopes = new SymbolScope[numScopes]; for (uint i = 0; i < numScopes; i++) scopes[i] = new SymbolScopeImpl(unScopes[i], method, this); children = scopes; } return children; } } volatile SymbolScope[] children; public override IList Locals { get { if (locals == null) { uint numVars; scope.GetLocals(0, out numVars, null); var unVars = new ISymUnmanagedVariable[numVars]; scope.GetLocals((uint)unVars.Length, out numVars, unVars); var vars = new SymbolVariable[numVars]; for (uint i = 0; i < numVars; i++) vars[i] = new SymbolVariableImpl(unVars[i]); locals = vars; } return locals; } } volatile SymbolVariable[] locals; public override IList Namespaces { get { if (namespaces == null) { uint numNss; scope.GetNamespaces(0, out numNss, null); var unNss = new ISymUnmanagedNamespace[numNss]; scope.GetNamespaces((uint)unNss.Length, out numNss, unNss); var nss = new SymbolNamespace[numNss]; for (uint i = 0; i < numNss; i++) nss[i] = new SymbolNamespaceImpl(unNss[i]); namespaces = nss; } return namespaces; } } volatile SymbolNamespace[] namespaces; public override IList CustomDebugInfos { get { return emptyPdbCustomDebugInfos; } } static readonly PdbCustomDebugInfo[] emptyPdbCustomDebugInfos = new PdbCustomDebugInfo[0]; public override PdbImportScope ImportScope { get { return null; } } public override IList GetConstants(ModuleDef module, GenericParamContext gpContext) { var scope2 = scope as ISymUnmanagedScope2; if (scope2 == null) return emptySymbolConstants; uint numCs; scope2.GetConstants(0, out numCs, null); if (numCs == 0) return emptySymbolConstants; var unCs = new ISymUnmanagedConstant[numCs]; scope2.GetConstants((uint)unCs.Length, out numCs, unCs); var nss = new PdbConstant[numCs]; for (uint i = 0; i < numCs; i++) { var unc = unCs[i]; var name = GetName(unc); object value; unc.GetValue(out value); var sigBytes = GetSignatureBytes(unc); TypeSig signature; if (sigBytes.Length == 0) signature = null; else signature = SignatureReader.ReadTypeSig(module, module.CorLibTypes, sigBytes, gpContext); nss[i] = new PdbConstant(name, signature, value); } return nss; } static readonly PdbConstant[] emptySymbolConstants = new PdbConstant[0]; string GetName(ISymUnmanagedConstant unc) { uint count; unc.GetName(0, out count, null); var chars = new char[count]; unc.GetName((uint)chars.Length, out count, chars); if (chars.Length == 0) return string.Empty; return new string(chars, 0, chars.Length - 1); } byte[] GetSignatureBytes(ISymUnmanagedConstant unc) { const int E_FAIL = unchecked((int)0x80004005); const int E_NOTIMPL = unchecked((int)0x80004001); uint bufSize; int hr = unc.GetSignature(0, out bufSize, null); if (bufSize == 0 || (hr < 0 && hr != E_FAIL && hr != E_NOTIMPL)) return emptyByteArray; var buffer = new byte[bufSize]; hr = unc.GetSignature((uint)buffer.Length, out bufSize, buffer); Debug.Assert(hr == 0); if (hr != 0) return emptyByteArray; return buffer; } static readonly byte[] emptyByteArray = new byte[0]; } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/SymbolVariableImpl.cs000066400000000000000000000023421325033663500226740ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.DotNet.Pdb.Symbols; using dnlib.DotNet.Pdb.WindowsPdb; namespace dnlib.DotNet.Pdb.Dss { sealed class SymbolVariableImpl : SymbolVariable { readonly ISymUnmanagedVariable variable; public SymbolVariableImpl(ISymUnmanagedVariable variable) { this.variable = variable; } public override int Index { get { uint result; variable.GetAddressField1(out result); return (int)result; } } public override PdbLocalAttributes Attributes { get { uint result; variable.GetAttributes(out result); if ((result & (uint)CorSymVarFlag.VAR_IS_COMP_GEN) != 0) return PdbLocalAttributes.DebuggerHidden; return PdbLocalAttributes.None; } } public override string Name { get { uint count; variable.GetName(0, out count, null); var chars = new char[count]; variable.GetName((uint)chars.Length, out count, chars); if (chars.Length == 0) return string.Empty; return new string(chars, 0, chars.Length - 1); } } public override PdbCustomDebugInfo[] CustomDebugInfos { get { return emptyPdbCustomDebugInfos; } } static readonly PdbCustomDebugInfo[] emptyPdbCustomDebugInfos = new PdbCustomDebugInfo[0]; } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/SymbolWriter.cs000066400000000000000000000217061325033663500216060ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics.SymbolStore; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using dnlib.DotNet.Pdb.WindowsPdb; using dnlib.DotNet.Writer; namespace dnlib.DotNet.Pdb.Dss { sealed class SymbolWriter : ISymbolWriter3 { readonly ISymUnmanagedWriter2 writer; readonly ISymUnmanagedAsyncMethodPropertiesWriter asyncMethodWriter; readonly string pdbFileName; readonly Stream pdbStream; bool closeCalled; public bool SupportsAsyncMethods { get { return asyncMethodWriter != null; } } /// /// Constructor /// /// Writer /// PDB file name public SymbolWriter(ISymUnmanagedWriter2 writer, string pdbFileName) { if (writer == null) throw new ArgumentNullException("writer"); if (pdbFileName == null) throw new ArgumentNullException("pdbFileName"); this.writer = writer; this.asyncMethodWriter = writer as ISymUnmanagedAsyncMethodPropertiesWriter; this.pdbFileName = pdbFileName; } /// /// Constructor /// /// Writer /// PDB file name /// PDB output stream public SymbolWriter(ISymUnmanagedWriter2 writer, string pdbFileName, Stream pdbStream) { if (writer == null) throw new ArgumentNullException("writer"); if (pdbStream == null) throw new ArgumentNullException("pdbStream"); this.writer = writer; this.asyncMethodWriter = writer as ISymUnmanagedAsyncMethodPropertiesWriter; this.pdbStream = pdbStream; this.pdbFileName = pdbFileName; } public void Abort() { writer.Abort(); } public void Close() { if (closeCalled) return; closeCalled = true; writer.Close(); } public void CloseMethod() { writer.CloseMethod(); } public void CloseNamespace() { writer.CloseNamespace(); } public void CloseScope(int endOffset) { writer.CloseScope((uint)endOffset); } public void DefineAsyncStepInfo(uint[] yieldOffsets, uint[] breakpointOffset, uint[] breakpointMethod) { if (asyncMethodWriter == null) throw new InvalidOperationException(); if (yieldOffsets.Length != breakpointOffset.Length || yieldOffsets.Length != breakpointMethod.Length) throw new ArgumentException(); asyncMethodWriter.DefineAsyncStepInfo((uint)yieldOffsets.Length, yieldOffsets, breakpointOffset, breakpointMethod); } public void DefineCatchHandlerILOffset(uint catchHandlerOffset) { if (asyncMethodWriter == null) throw new InvalidOperationException(); asyncMethodWriter.DefineCatchHandlerILOffset(catchHandlerOffset); } public void DefineConstant(string name, object value, byte[] signature) { writer.DefineConstant(name, value, (uint)signature.Length, signature); } public void DefineConstant2(string name, object value, uint sigToken) { writer.DefineConstant2(name, value, sigToken); } public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType) { ISymUnmanagedDocumentWriter unDocWriter; writer.DefineDocument(url, ref language, ref languageVendor, ref documentType, out unDocWriter); return unDocWriter == null ? null : new SymbolDocumentWriter(unDocWriter); } public void DefineField(SymbolToken parent, string name, System.Reflection.FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3) { writer.DefineField((uint)parent.GetToken(), name, (uint)attributes, (uint)signature.Length, signature, (uint)addrKind, (uint)addr1, (uint)addr2, (uint)addr3); } public void DefineGlobalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3) { writer.DefineGlobalVariable(name, (uint)attributes, (uint)signature.Length, signature, (uint)addrKind, (uint)addr1, (uint)addr2, (uint)addr3); } public void DefineGlobalVariable2(string name, uint attributes, uint sigToken, uint addrKind, uint addr1, uint addr2, uint addr3) { writer.DefineGlobalVariable2(name, attributes, sigToken, addrKind, addr1, addr2, addr3); } public void DefineKickoffMethod(uint kickoffMethod) { if (asyncMethodWriter == null) throw new InvalidOperationException(); asyncMethodWriter.DefineKickoffMethod(kickoffMethod); } public void DefineLocalVariable(string name, System.Reflection.FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset) { writer.DefineLocalVariable(name, (uint)attributes, (uint)signature.Length, signature, (uint)addrKind, (uint)addr1, (uint)addr2, (uint)addr3, (uint)startOffset, (uint)endOffset); } public void DefineParameter(string name, ParameterAttributes attributes, int sequence, SymAddressKind addrKind, int addr1, int addr2, int addr3) { writer.DefineParameter(name, (uint)attributes, (uint)sequence, (uint)addrKind, (uint)addr1, (uint)addr2, (uint)addr3); } public void DefineSequencePoints(ISymbolDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns) { var doc = document as SymbolDocumentWriter; if (doc == null) throw new ArgumentException("document isn't a non-null SymbolDocumentWriter instance"); if (offsets == null || lines == null || columns == null || endLines == null || endColumns == null || offsets.Length != lines.Length || offsets.Length != columns.Length || offsets.Length != endLines.Length || offsets.Length != endColumns.Length) throw new ArgumentException("Invalid arrays"); writer.DefineSequencePoints(doc.SymUnmanagedDocumentWriter, (uint)offsets.Length, offsets, lines, columns, endLines, endColumns); } public void DefineSequencePoints(ISymbolDocumentWriter document, uint arraySize, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns) { var doc = document as SymbolDocumentWriter; if (doc == null) throw new ArgumentException("document isn't a non-null SymbolDocumentWriter instance"); writer.DefineSequencePoints(doc.SymUnmanagedDocumentWriter, arraySize, offsets, lines, columns, endLines, endColumns); } public void Initialize(IntPtr emitter, string filename, bool fFullBuild) { writer.Initialize(emitter, filename, null, fFullBuild); } public void OpenMethod(SymbolToken method) { writer.OpenMethod((uint)method.GetToken()); } public void OpenNamespace(string name) { writer.OpenNamespace(name); } public int OpenScope(int startOffset) { uint result; writer.OpenScope((uint)startOffset, out result); return (int)result; } public void RemapToken(uint oldToken, uint newToken) { writer.RemapToken(oldToken, newToken); } public void SetMethodSourceRange(ISymbolDocumentWriter startDoc, int startLine, int startColumn, ISymbolDocumentWriter endDoc, int endLine, int endColumn) { var sdoc = startDoc as SymbolDocumentWriter; if (sdoc == null) throw new ArgumentException("startDoc isn't a non-null SymbolDocumentWriter instance"); var edoc = endDoc as SymbolDocumentWriter; if (edoc == null) throw new ArgumentException("endDoc isn't a non-null SymbolDocumentWriter instance"); writer.SetMethodSourceRange(sdoc.SymUnmanagedDocumentWriter, (uint)startLine, (uint)startColumn, edoc.SymUnmanagedDocumentWriter, (uint)endLine, (uint)endColumn); } public void SetScopeRange(int scopeID, int startOffset, int endOffset) { writer.SetScopeRange((uint)scopeID, (uint)startOffset, (uint)endOffset); } public void SetSymAttribute(SymbolToken parent, string name, byte[] data) { writer.SetSymAttribute((uint)parent.GetToken(), name, (uint)data.Length, data); } public void SetUnderlyingWriter(IntPtr underlyingWriter) { throw new NotSupportedException(); } public void SetUserEntryPoint(SymbolToken entryMethod) { writer.SetUserEntryPoint((uint)entryMethod.GetToken()); } public void UsingNamespace(string fullName) { writer.UsingNamespace(fullName); } public byte[] GetDebugInfo(out IMAGE_DEBUG_DIRECTORY pIDD) { uint size; writer.GetDebugInfo(out pIDD, 0, out size, null); var buffer = new byte[size]; writer.GetDebugInfo(out pIDD, size, out size, buffer); return buffer; } public void DefineLocalVariable2(string name, uint attributes, uint sigToken, uint addrKind, uint addr1, uint addr2, uint addr3, uint startOffset, uint endOffset) { writer.DefineLocalVariable2(name, attributes, sigToken, addrKind, addr1, addr2, addr3, startOffset, endOffset); } public void Initialize(MetaData metaData) { if (pdbStream != null) writer.Initialize(new MDEmitter(metaData), pdbFileName, new StreamIStream(pdbStream), true); else if (!string.IsNullOrEmpty(pdbFileName)) writer.Initialize(new MDEmitter(metaData), pdbFileName, null, true); else throw new InvalidOperationException(); } public void Dispose() { Marshal.FinalReleaseComObject(writer); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Dss/SymbolWriterCreator.cs000066400000000000000000000030611325033663500231200ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using dnlib.DotNet.Pdb.WindowsPdb; namespace dnlib.DotNet.Pdb.Dss { /// /// Creates a /// static class SymbolWriterCreator { static readonly Guid CLSID_CorSymWriter_SxS = new Guid(0x0AE2DEB0, 0xF901, 0x478B, 0xBB, 0x9F, 0x88, 0x1E, 0xE8, 0x06, 0x67, 0x88); /// /// Creates a instance /// /// A new instance public static ISymUnmanagedWriter2 CreateSymUnmanagedWriter2() { return (ISymUnmanagedWriter2)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_CorSymWriter_SxS)); } /// /// Creates a new instance /// /// PDB file name /// A new instance public static ISymbolWriter2 Create(string pdbFileName) { if (File.Exists(pdbFileName)) File.Delete(pdbFileName); return new SymbolWriter(CreateSymUnmanagedWriter2(), pdbFileName); } /// /// Creates a new instance /// /// PDB output stream /// PDB file name /// A new instance public static ISymbolWriter2 Create(Stream pdbStream, string pdbFileName) { return new SymbolWriter(CreateSymUnmanagedWriter2(), pdbFileName, pdbStream); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/IMAGE_DEBUG_DIRECTORY.cs000066400000000000000000000007521325033663500215650ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.PE; namespace dnlib.DotNet.Pdb { /// /// IMAGE_DEBUG_DIRECTORY /// public struct IMAGE_DEBUG_DIRECTORY { #pragma warning disable 1591 public uint Characteristics; public uint TimeDateStamp; public ushort MajorVersion; public ushort MinorVersion; public ImageDebugType Type; public uint SizeOfData; public uint AddressOfRawData; public uint PointerToRawData; #pragma warning restore 1591 } } dnlib-2.1_VS2010/src/DotNet/Pdb/ImageStreamUtils.cs000066400000000000000000000010371325033663500216250ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using System.Security; using dnlib.IO; namespace dnlib.DotNet.Pdb { static class ImageStreamUtils { public static IImageStream OpenImageStream(string fileName) { try { if (!File.Exists(fileName)) return null; // Don't use memory mapped I/O return MemoryImageStream.Create(File.ReadAllBytes(fileName)); } catch (IOException) { } catch (UnauthorizedAccessException) { } catch (SecurityException) { } return null; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/000077500000000000000000000000001325033663500174125ustar00rootroot00000000000000dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/DbiDocument.cs000066400000000000000000000027761325033663500221520ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics.SymbolStore; using dnlib.DotNet.Pdb.Symbols; using dnlib.IO; namespace dnlib.DotNet.Pdb.Managed { sealed class DbiDocument : SymbolDocument { readonly string url; Guid language; Guid languageVendor; Guid documentType; Guid checkSumAlgorithmId; byte[] checkSum; public override string URL { get { return url; } } public override Guid Language { get { return language; } } public override Guid LanguageVendor { get { return languageVendor; } } public override Guid DocumentType { get { return documentType; } } public override Guid CheckSumAlgorithmId { get { return checkSumAlgorithmId; } } public override byte[] CheckSum { get { return checkSum; } } public override PdbCustomDebugInfo[] CustomDebugInfos { get { return emptyPdbCustomDebugInfos; } } static readonly PdbCustomDebugInfo[] emptyPdbCustomDebugInfos = new PdbCustomDebugInfo[0]; public DbiDocument(string url) { this.url = url; documentType = SymDocumentType.Text; } public void Read(IImageStream stream) { stream.Position = 0; language = new Guid(stream.ReadBytes(0x10)); languageVendor = new Guid(stream.ReadBytes(0x10)); documentType = new Guid(stream.ReadBytes(0x10)); checkSumAlgorithmId = new Guid(stream.ReadBytes(0x10)); var len = stream.ReadInt32(); if (stream.ReadUInt32() != 0) throw new PdbException("Unexpected value"); checkSum = stream.ReadBytes(len); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/DbiFunction.cs000066400000000000000000000067101325033663500221510ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using dnlib.DotNet.Emit; using dnlib.DotNet.Pdb.Symbols; using dnlib.IO; namespace dnlib.DotNet.Pdb.Managed { sealed class DbiFunction : SymbolMethod { public override int Token { get { return token; } } internal int token; internal PdbReader reader; public string Name { get; private set; } public PdbAddress Address { get; private set; } public DbiScope Root { get; private set; } public List Lines { get { return lines; } set { lines = value; } } List lines; public void Read(IImageStream stream, long recEnd) { stream.Position += 4; var end = stream.ReadUInt32(); stream.Position += 4; var len = stream.ReadUInt32(); stream.Position += 8; token = stream.ReadInt32(); Address = PdbAddress.ReadAddress(stream); stream.Position += 1 + 2; Name = PdbReader.ReadCString(stream); stream.Position = recEnd; Root = new DbiScope(this, null, "", Address.Offset, len); Root.Read(new RecursionCounter(), stream, end); FixOffsets(new RecursionCounter(), Root); } void FixOffsets(RecursionCounter counter, DbiScope scope) { if (!counter.Increment()) return; scope.startOffset -= (int)Address.Offset; scope.endOffset -= (int)Address.Offset; foreach (var child in scope.Children) FixOffsets(counter, (DbiScope)child); counter.Decrement(); } public override SymbolScope RootScope { get { return Root; } } public override IList SequencePoints { get { var l = lines; if (l == null) return emptySymbolSequencePoints; return l; } } static readonly SymbolSequencePoint[] emptySymbolSequencePoints = new SymbolSequencePoint[0]; const string asyncMethodInfoAttributeName = "asyncMethodInfo"; public int AsyncKickoffMethod { get { var data = Root.GetSymAttribute(asyncMethodInfoAttributeName); if (data == null) return 0; return BitConverter.ToInt32(data, 0); } } public uint? AsyncCatchHandlerILOffset { get { var data = Root.GetSymAttribute(asyncMethodInfoAttributeName); if (data == null) return null; uint token = BitConverter.ToUInt32(data, 4); return token == uint.MaxValue ? (uint?)null : token; } } public IList AsyncStepInfos { get { if (asyncStepInfos == null) asyncStepInfos = CreateSymbolAsyncStepInfos(); return asyncStepInfos; } } volatile SymbolAsyncStepInfo[] asyncStepInfos; SymbolAsyncStepInfo[] CreateSymbolAsyncStepInfos() { var data = Root.GetSymAttribute(asyncMethodInfoAttributeName); if (data == null) return emptySymbolAsyncStepInfos; int pos = 8; int count = BitConverter.ToInt32(data, pos); pos += 4; if (pos + (long)count * 12 > data.Length) return emptySymbolAsyncStepInfos; if (count == 0) return emptySymbolAsyncStepInfos; var res = new SymbolAsyncStepInfo[count]; for (int i = 0; i < res.Length; i++) { res[i] = new SymbolAsyncStepInfo(BitConverter.ToUInt32(data, pos), BitConverter.ToUInt32(data, pos + 8), BitConverter.ToUInt32(data, pos + 4)); pos += 12; } return res; } static readonly SymbolAsyncStepInfo[] emptySymbolAsyncStepInfos = new SymbolAsyncStepInfo[0]; public override void GetCustomDebugInfos(MethodDef method, CilBody body, IList result) { reader.GetCustomDebugInfos(this, method, body, result); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/DbiModule.cs000066400000000000000000000127751325033663500216210ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using dnlib.DotNet.Pdb.Symbols; using dnlib.IO; namespace dnlib.DotNet.Pdb.Managed { sealed class DbiModule { public DbiModule() { Functions = new List(); Documents = new List(); } public ushort StreamId { get; private set; } uint cbSyms; uint cbOldLines; uint cbLines; public string ModuleName { get; private set; } public string ObjectName { get; private set; } public IList Functions { get; private set; } public IList Documents { get; private set; } public void Read(IImageStream stream) { stream.Position += 34; StreamId = stream.ReadUInt16(); cbSyms = stream.ReadUInt32(); cbOldLines = stream.ReadUInt32(); cbLines = stream.ReadUInt32(); stream.Position += 16; if ((int)cbSyms < 0) cbSyms = 0; if ((int)cbOldLines < 0) cbOldLines = 0; if ((int)cbLines < 0) cbLines = 0; ModuleName = PdbReader.ReadCString(stream); ObjectName = PdbReader.ReadCString(stream); stream.Position = (stream.Position + 3) & (~3); } public void LoadFunctions(PdbReader reader, IImageStream stream) { stream.Position = 0; using (var substream = stream.Create(stream.FileOffset + stream.Position, cbSyms)) ReadFunctions(substream); if (Functions.Count > 0) { stream.Position += cbSyms + cbOldLines; using (var substream = stream.Create(stream.FileOffset + stream.Position, cbLines)) ReadLines(reader, substream); } } void ReadFunctions(IImageStream stream) { if (stream.ReadUInt32() != 4) throw new PdbException("Invalid signature"); while (stream.Position < stream.Length) { var size = stream.ReadUInt16(); var begin = stream.Position; var end = begin + size; var type = (SymbolType)stream.ReadUInt16(); switch (type) { case SymbolType.S_GMANPROC: case SymbolType.S_LMANPROC: var func = new DbiFunction(); func.Read(stream, end); Functions.Add(func); break; default: stream.Position = end; break; } } } void ReadLines(PdbReader reader, IImageStream stream) { var docs = new Dictionary(); stream.Position = 0; while (stream.Position < stream.Length) { var sig = (ModuleStreamType)stream.ReadUInt32(); var size = stream.ReadUInt32(); var begin = stream.Position; var end = (begin + size + 3) & ~3; if (sig == ModuleStreamType.FileInfo) ReadFiles(reader, docs, stream, end); stream.Position = end; } var sortedFuncs = new DbiFunction[Functions.Count]; Functions.CopyTo(sortedFuncs, 0); Array.Sort(sortedFuncs, (a, b) => a.Address.CompareTo(b.Address)); stream.Position = 0; while (stream.Position < stream.Length) { var sig = (ModuleStreamType)stream.ReadUInt32(); var size = stream.ReadUInt32(); var begin = stream.Position; var end = begin + size; if (sig == ModuleStreamType.Lines) ReadLines(sortedFuncs, docs, stream, end); stream.Position = end; } } void ReadFiles(PdbReader reader, Dictionary documents, IImageStream stream, long end) { var begin = stream.Position; while (stream.Position < end) { var id = stream.Position - begin; var nameId = stream.ReadUInt32(); var len = stream.ReadByte(); /*var type = */stream.ReadByte(); var doc = reader.GetDocument(nameId); documents.Add(id, doc); stream.Position += len; stream.Position = (stream.Position + 3) & (~3); } } void ReadLines(DbiFunction[] funcs, Dictionary documents, IImageStream stream, long end) { var address = PdbAddress.ReadAddress(stream); int first = 0; int last = funcs.Length - 1; int found = -1; while (first <= last) { var index = first + ((last - first) >> 1); var addr = funcs[index].Address; if (addr < address) { first = index + 1; } else if (addr > address) { last = index - 1; } else { found = index; break; } } if (found == -1) return; var flags = stream.ReadUInt16(); stream.Position += 4; if (funcs[found].Lines == null) { while (found > 0) { var prevFunc = funcs[found - 1]; if (prevFunc != null || prevFunc.Address != address) break; found--; } } else { while (found < funcs.Length - 1 && funcs[found] != null) { var nextFunc = funcs[found + 1]; if (nextFunc.Address != address) break; found++; } } var func = funcs[found]; if (func.Lines != null) return; func.Lines = new List(); while (stream.Position < end) { var document = documents[stream.ReadUInt32()]; var count = stream.ReadUInt32(); stream.Position += 4; const int LINE_ENTRY_SIZE = 8; const int COL_ENTRY_SIZE = 4; var lineTablePos = stream.Position; var colTablePos = stream.Position + count * LINE_ENTRY_SIZE; for (uint i = 0; i < count; i++) { stream.Position = lineTablePos + i * LINE_ENTRY_SIZE; var line = new SymbolSequencePoint { Document = document }; line.Offset = stream.ReadInt32(); var lineFlags = stream.ReadUInt32(); line.Line = (int)(lineFlags & 0x00ffffff); line.EndLine = line.Line + (int)((lineFlags >> 24) & 0x7F); if ((flags & 1) != 0) { stream.Position = colTablePos + i * COL_ENTRY_SIZE; line.Column = stream.ReadUInt16(); line.EndColumn = stream.ReadUInt16(); } func.Lines.Add(line); } } } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/DbiNamespace.cs000066400000000000000000000004601325033663500222540ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet.Pdb.Managed { sealed class DbiNamespace : SymbolNamespace { public override string Name { get { return name; } } readonly string name; public DbiNamespace(string ns) { name = ns; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/DbiScope.cs000066400000000000000000000143331325033663500214350ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Diagnostics; using System.Text; using dnlib.DotNet.Pdb.Symbols; using dnlib.IO; namespace dnlib.DotNet.Pdb.Managed { sealed class DbiScope : SymbolScope { readonly SymbolMethod method; readonly SymbolScope parent; internal int startOffset; internal int endOffset; readonly List childrenList; readonly List localsList; readonly List namespacesList; public override SymbolMethod Method { get { return method; } } public override SymbolScope Parent { get { return parent; } } public override int StartOffset { get { return startOffset; } } public override int EndOffset { get { return endOffset; } } public override IList Children { get { return childrenList; } } public override IList Locals { get { return localsList; } } public override IList Namespaces { get { return namespacesList; } } public override IList CustomDebugInfos { get { return emptyPdbCustomDebugInfos; } } static readonly PdbCustomDebugInfo[] emptyPdbCustomDebugInfos = new PdbCustomDebugInfo[0]; public override PdbImportScope ImportScope { get { return null; } } public DbiScope(SymbolMethod method, SymbolScope parent, string name, uint offset, uint length) { this.method = method; this.parent = parent; Name = name; startOffset = (int)offset; endOffset = (int)(offset + length); childrenList = new List(); localsList = new List(); namespacesList = new List(); } public string Name { get; private set; } List oemInfos; List constants; struct ConstantInfo { public string Name; public uint SignatureToken; public object Value; public ConstantInfo(string name, uint signatureToken, object value) { Name = name; SignatureToken = signatureToken; Value = value; } } internal struct OemInfo { public readonly string Name; public readonly byte[] Data; public OemInfo(string name, byte[] data) { Name = name; Data = data; } public override string ToString() { return Name + " = (" + Data.Length.ToString() + " bytes)"; } } static readonly byte[] dotNetOemGuid = new byte[] { 0xC9, 0x3F, 0xEA, 0xC6, 0xB3, 0x59, 0xD6, 0x49, 0xBC, 0x25, 0x09, 0x02, 0xBB, 0xAB, 0xB4, 0x60 }; public void Read(RecursionCounter counter, IImageStream stream, uint scopeEnd) { if (!counter.Increment()) throw new PdbException("Scopes too deep"); while (stream.Position < scopeEnd) { var size = stream.ReadUInt16(); var begin = stream.Position; var end = begin + size; var type = (SymbolType)stream.ReadUInt16(); DbiScope child = null; uint? childEnd = null; string name; switch (type) { case SymbolType.S_BLOCK32: { stream.Position += 4; childEnd = stream.ReadUInt32(); var len = stream.ReadUInt32(); var addr = PdbAddress.ReadAddress(stream); name = PdbReader.ReadCString(stream); child = new DbiScope(method, this, name, addr.Offset, len); break; } case SymbolType.S_UNAMESPACE: namespacesList.Add(new DbiNamespace(PdbReader.ReadCString(stream))); break; case SymbolType.S_MANSLOT: { var variable = new DbiVariable(); variable.Read(stream); localsList.Add(variable); break; } case SymbolType.S_OEM: if (stream.Position + 20 > end) break; if (!ReadAndCompareBytes(stream, end, dotNetOemGuid)) { Debug.Fail("Unknown OEM record GUID, not .NET GUID"); break; } stream.Position += 4;// typeIndex or 0 name = ReadUnicodeString(stream, end); Debug.Assert(name != null); if (name == null) break; var data = stream.ReadBytes((int)(end - stream.Position)); if (oemInfos == null) oemInfos = new List(1); oemInfos.Add(new OemInfo(name, data)); break; case SymbolType.S_MANCONSTANT: uint signatureToken = stream.ReadUInt32(); object value; if (!NumericReader.TryReadNumeric(stream, end, out value)) break; name = PdbReader.ReadCString(stream); if (constants == null) constants = new List(); constants.Add(new ConstantInfo(name, signatureToken, value)); break; case SymbolType.S_END: break; default: break; } stream.Position = end; if (child != null) { child.Read(counter, stream, childEnd.Value); childrenList.Add(child); child = null; } } counter.Decrement(); if (stream.Position != scopeEnd) Debugger.Break(); } static string ReadUnicodeString(IImageStream stream, long end) { var sb = new StringBuilder(); for (;;) { if (stream.Position + 2 > end) return null; var c = (char)stream.ReadUInt16(); if (c == 0) break; sb.Append(c); } return sb.ToString(); } static bool ReadAndCompareBytes(IImageStream stream, long end, byte[] bytes) { if (stream.Position + bytes.Length > end) return false; for (int i = 0; i < bytes.Length; i++) { if (stream.ReadByte() != bytes[i]) return false; } return true; } public override IList GetConstants(ModuleDef module, GenericParamContext gpContext) { if (constants == null) return emptySymbolConstants; var res = new PdbConstant[constants.Count]; for (int i = 0; i < res.Length; i++) { var info = constants[i]; TypeSig signature; var saSig = module.ResolveToken(info.SignatureToken, gpContext) as StandAloneSig; var fieldSig = saSig == null ? null : saSig.Signature as FieldSig; if (fieldSig == null) { Debug.Fail("Constant without a signature"); signature = null; } else signature = fieldSig.Type; res[i] = new PdbConstant(info.Name, signature, info.Value); } return res; } static readonly PdbConstant[] emptySymbolConstants = new PdbConstant[0]; internal byte[] GetSymAttribute(string name) { if (oemInfos == null) return null; foreach (var info in oemInfos) { if (info.Name == name) return info.Data; } return null; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/DbiVariable.cs000066400000000000000000000020411325033663500221020ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.DotNet.Pdb.Symbols; using dnlib.IO; namespace dnlib.DotNet.Pdb.Managed { sealed class DbiVariable : SymbolVariable { public override string Name { get { return name; } } string name; public override PdbLocalAttributes Attributes { get { return attributes; } } PdbLocalAttributes attributes; public override int Index { get { return index; } } int index; public override PdbCustomDebugInfo[] CustomDebugInfos { get { return emptyPdbCustomDebugInfos; } } static readonly PdbCustomDebugInfo[] emptyPdbCustomDebugInfos = new PdbCustomDebugInfo[0]; public void Read(IImageStream stream) { index = stream.ReadInt32(); stream.Position += 10; attributes = GetAttributes(stream.ReadUInt16()); name = PdbReader.ReadCString(stream); } static PdbLocalAttributes GetAttributes(uint flags) { PdbLocalAttributes res = 0; const int fCompGenx = 4; if ((flags & fCompGenx) != 0) res |= PdbLocalAttributes.DebuggerHidden; return res; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/ModuleStreamType.cs000066400000000000000000000006051325033663500232050ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Pdb.Managed { enum ModuleStreamType : uint { Symbols = 0xF1, Lines = 0xF2, StringTable = 0xF3, FileInfo = 0xF4, FrameData = 0xF5, InlineeLines = 0xF6, CrossScopeImports = 0xF7, CrossScopeExports = 0xF8, ILLines = 0xF9, FuncMDTokenMap = 0xFA, TypeMDTokenMap = 0xFB, MergedAssemblyInput = 0xFC, } }dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/MsfStream.cs000066400000000000000000000010241325033663500216370ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; namespace dnlib.DotNet.Pdb.Managed { sealed class MsfStream { public MsfStream(IImageStream[] pages, uint length) { byte[] buf = new byte[length]; int offset = 0; foreach (var page in pages) { page.Position = 0; int len = Math.Min((int)page.Length, (int)(length - offset)); offset += page.Read(buf, offset, len); } Content = new MemoryImageStream(0, buf, 0, buf.Length); } public IImageStream Content { get; set; } } }dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/NumericLeaf.cs000066400000000000000000000015641325033663500221410ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Pdb.Managed { enum NumericLeaf : ushort { LF_NUMERIC = 0x8000, LF_CHAR = 0x8000, LF_SHORT = 0x8001, LF_USHORT = 0x8002, LF_LONG = 0x8003, LF_ULONG = 0x8004, LF_REAL32 = 0x8005, LF_REAL64 = 0x8006, LF_REAL80 = 0x8007, LF_REAL128 = 0x8008, LF_QUADWORD = 0x8009, LF_UQUADWORD = 0x800A, LF_REAL48 = 0x800B, LF_COMPLEX32 = 0x800C, LF_COMPLEX64 = 0x800D, LF_COMPLEX80 = 0x800E, LF_COMPLEX128 = 0x800F, LF_VARSTRING = 0x8010, LF_RESERVED_8011 = 0x8011, LF_RESERVED_8012 = 0x8012, LF_RESERVED_8013 = 0x8013, LF_RESERVED_8014 = 0x8014, LF_RESERVED_8015 = 0x8015, LF_RESERVED_8016 = 0x8016, LF_OCTWORD = 0x8017, LF_UOCTWORD = 0x8018, LF_VARIANT = 0x8019, LF_DATE = 0x801A, LF_UTF8STRING = 0x801B, LF_REAL16 = 0x801C, } } dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/NumericReader.cs000066400000000000000000000045141325033663500224720ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Text; using dnlib.IO; namespace dnlib.DotNet.Pdb.Managed { static class NumericReader { public static bool TryReadNumeric(IImageStream stream, long end, out object value) { value = null; if (stream.Position + 2 > end) return false; var numLeaf = (NumericLeaf)stream.ReadUInt16(); if (numLeaf < NumericLeaf.LF_NUMERIC) { value = (short)numLeaf; return true; } switch (numLeaf) { case NumericLeaf.LF_CHAR: if (stream.Position > end) return false; value = stream.ReadSByte(); return true; case NumericLeaf.LF_SHORT: if (stream.Position + 2 > end) return false; value = stream.ReadInt16(); return true; case NumericLeaf.LF_USHORT: if (stream.Position + 2 > end) return false; value = stream.ReadUInt16(); return true; case NumericLeaf.LF_LONG: if (stream.Position + 4 > end) return false; value = stream.ReadInt32(); return true; case NumericLeaf.LF_ULONG: if (stream.Position + 4 > end) return false; value = stream.ReadUInt32(); return true; case NumericLeaf.LF_REAL32: if (stream.Position + 4 > end) return false; value = stream.ReadSingle(); return true; case NumericLeaf.LF_REAL64: if (stream.Position + 8 > end) return false; value = stream.ReadDouble(); return true; case NumericLeaf.LF_QUADWORD: if (stream.Position + 8 > end) return false; value = stream.ReadInt64(); return true; case NumericLeaf.LF_UQUADWORD: if (stream.Position + 8 > end) return false; value = stream.ReadUInt64(); return true; case NumericLeaf.LF_VARSTRING: if (stream.Position + 2 > end) return false; int varStrLen = stream.ReadUInt16(); if (stream.Position + varStrLen > end) return false; value = Encoding.UTF8.GetString(stream.ReadBytes(varStrLen)); return true; case NumericLeaf.LF_VARIANT: if (stream.Position + 0x10 > end) return false; int v0 = stream.ReadInt32(); int v1 = stream.ReadInt32(); int v2 = stream.ReadInt32(); int v3 = stream.ReadInt32(); byte scale = (byte)(v0 >> 16); if (scale <= 28) value = new decimal(v2, v3, v1, v0 < 0, scale); else value = null; return true; default: return false; } } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/PdbAddress.cs000066400000000000000000000117471325033663500217660ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using dnlib.IO; namespace dnlib.DotNet.Pdb.Managed { /// /// An address in the image /// [DebuggerDisplay("{Section}:{Offset}")] struct PdbAddress : IEquatable, IComparable { /// /// Section /// public readonly ushort Section; /// /// Offset in /// public readonly uint Offset; /// /// Constructor /// /// Section /// Offset in public PdbAddress(ushort section, int offset) { this.Section = section; this.Offset = (uint)offset; } /// /// Constructor /// /// Section /// Offset in public PdbAddress(ushort section, uint offset) { this.Section = section; this.Offset = offset; } /// /// Returns true if is less than or equal to /// /// First /// Second /// public static bool operator <=(PdbAddress a, PdbAddress b) { return a.CompareTo(b) <= 0; } /// /// Returns true if is less than /// /// First /// Second /// public static bool operator <(PdbAddress a, PdbAddress b) { return a.CompareTo(b) < 0; } /// /// Returns true if is greater than or equal to /// /// First /// Second /// public static bool operator >=(PdbAddress a, PdbAddress b) { return a.CompareTo(b) >= 0; } /// /// Returns true if is greater than /// /// First /// Second /// public static bool operator >(PdbAddress a, PdbAddress b) { return a.CompareTo(b) > 0; } /// /// Returns true if is equal to /// /// First /// Second /// public static bool operator ==(PdbAddress a, PdbAddress b) { return a.Equals(b); } /// /// Returns true if is not equal to /// /// First /// Second /// public static bool operator !=(PdbAddress a, PdbAddress b) { return !a.Equals(b); } /// /// Compares this instance with and returns less than 0 if it's /// less than , 0 if it's equal to and /// greater than 0 if it's greater than /// /// Other instance /// public int CompareTo(PdbAddress other) { if (Section != other.Section) return Section.CompareTo(other.Section); return Offset.CompareTo(other.Offset); } /// /// Compares this to another instance /// /// The other one /// true if they're equal public bool Equals(PdbAddress other) { return Section == other.Section && Offset == other.Offset; } /// /// Compares this to another instance /// /// The other one /// true if they're equal public override bool Equals(object obj) { if (!(obj is PdbAddress)) return false; return Equals((PdbAddress)obj); } /// /// Gets the hash code /// /// Hash code public override int GetHashCode() { return (Section << 16) ^ (int)Offset; } /// /// ToString() override /// /// public override string ToString() { return string.Format("{0:X4}:{1:X8}", Section, Offset); } /// /// Reads a 32-bit offset followed by a 16-bit section and creates a new /// /// Reader /// public static PdbAddress ReadAddress(IBinaryReader reader) { uint offs = reader.ReadUInt32(); return new PdbAddress(reader.ReadUInt16(), offs); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/PdbException.cs000066400000000000000000000020311325033663500223210ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Runtime.Serialization; namespace dnlib.DotNet.Pdb.Managed { /// /// Exception that is thrown when encounters an error. /// [Serializable] sealed class PdbException : Exception { /// /// Constructor /// public PdbException() { } /// /// Constructor /// /// Exception message public PdbException(string message) : base("Failed to read PDB: " + message) { } /// /// Constructor /// /// Inner exception public PdbException(Exception innerException) : base("Failed to read PDB: " + innerException.Message, innerException) { } /// /// Constructor /// /// /// public PdbException(SerializationInfo info, StreamingContext context) : base(info, context) { } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/PdbReader.cs000066400000000000000000000246711325033663500216030ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections; using System.Collections.Generic; using System.Text; using dnlib.DotNet.Emit; using dnlib.DotNet.Pdb.Symbols; using dnlib.DotNet.Pdb.WindowsPdb; using dnlib.IO; namespace dnlib.DotNet.Pdb.Managed { /// /// A managed PDB reader implementation for .NET modules. /// sealed class PdbReader : SymbolReader { MsfStream[] streams; Dictionary names; Dictionary strings; List modules; ModuleDef module; const int STREAM_ROOT = 0; const int STREAM_NAMES = 1; const int STREAM_TPI = 2; const int STREAM_DBI = 3; const ushort STREAM_INVALID_INDEX = ushort.MaxValue; Dictionary documents; Dictionary functions; uint entryPt; public override PdbFileKind PdbFileKind { get { return PdbFileKind.WindowsPDB; } } /// /// The age of PDB file. /// public uint Age { get; private set; } /// /// The GUID of PDB file. /// public Guid Guid { get; private set; } public override void Initialize(ModuleDef module) { this.module = module; } /// /// Read the PDB in the specified stream. /// /// The stream that contains the PDB file public void Read(IImageStream stream) { try { ReadInternal(stream); } catch (Exception ex) { if (ex is PdbException) throw; throw new PdbException(ex); } finally { streams = null; names = null; strings = null; modules = null; } } static uint RoundUpDiv(uint value, uint divisor) { return (value + divisor - 1) / divisor; } void ReadInternal(IImageStream stream) { stream.Position = 0; string sig = Encoding.ASCII.GetString(stream.ReadBytes(30)); if (sig != "Microsoft C/C++ MSF 7.00\r\n\u001ADS\0") throw new PdbException("Invalid signature"); stream.Position += 2; uint pageSize = stream.ReadUInt32(); /*uint fpm = */stream.ReadUInt32(); uint pageCount = stream.ReadUInt32(); uint rootSize = stream.ReadUInt32(); stream.ReadUInt32(); var numOfRootPages = RoundUpDiv(rootSize, pageSize); var numOfPtrPages = RoundUpDiv(numOfRootPages * 4, pageSize); if (pageCount * pageSize != stream.Length) throw new PdbException("File size mismatch"); var pages = new IImageStream[pageCount]; try { FileOffset offset = 0; for (uint i = 0; i < pageCount; i++) { pages[i] = stream.Create(offset, pageSize); offset += pageSize; } var rootPages = new IImageStream[numOfRootPages]; int pageIndex = 0; for (int i = 0; i < numOfPtrPages && pageIndex < numOfRootPages; i++) { var ptrPage = pages[stream.ReadUInt32()]; ptrPage.Position = 0; for (; ptrPage.Position < ptrPage.Length && pageIndex < numOfRootPages; pageIndex++) rootPages[pageIndex] = pages[ptrPage.ReadUInt32()]; } ReadRootDirectory(new MsfStream(rootPages, rootSize), pages, pageSize); } finally { foreach (var page in pages) { if (page != null) page.Dispose(); } } ReadNames(); ReadStringTable(); var tokenMapStream = ReadModules(); documents = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (var module in modules) { if (IsValidStreamIndex(module.StreamId)) module.LoadFunctions(this, streams[module.StreamId].Content); } if (IsValidStreamIndex(tokenMapStream ?? STREAM_INVALID_INDEX)) ApplyRidMap(streams[tokenMapStream.Value].Content); functions = new Dictionary(); foreach (var module in modules) { foreach (var func in module.Functions) { func.reader = this; functions.Add(func.Token, func); } } } bool IsValidStreamIndex(ushort index) { return index != STREAM_INVALID_INDEX && index < streams.Length; } void ReadRootDirectory(MsfStream stream, IImageStream[] pages, uint pageSize) { uint streamNum = stream.Content.ReadUInt32(); uint[] streamSizes = new uint[streamNum]; for (int i = 0; i < streamSizes.Length; i++) streamSizes[i] = stream.Content.ReadUInt32(); streams = new MsfStream[streamNum]; for (int i = 0; i < streamSizes.Length; i++) { if (streamSizes[i] == 0xffffffff) { streams[i] = null; continue; } var pageCount = RoundUpDiv(streamSizes[i], pageSize); var streamPages = new IImageStream[pageCount]; for (int j = 0; j < streamPages.Length; j++) streamPages[j] = pages[stream.Content.ReadUInt32()]; streams[i] = new MsfStream(streamPages, streamSizes[i]); } } void ReadNames() { var stream = streams[STREAM_NAMES].Content; stream.Position = 8; Age = stream.ReadUInt32(); Guid = new Guid(stream.ReadBytes(0x10)); uint nameSize = stream.ReadUInt32(); using (var nameData = stream.Create(stream.FileOffset + stream.Position, nameSize)) { stream.Position += nameSize; /*uint entryCount = */stream.ReadUInt32(); uint entryCapacity = stream.ReadUInt32(); var entryOk = new BitArray(stream.ReadBytes(stream.ReadInt32() * 4)); if (stream.ReadUInt32() != 0) throw new NotSupportedException(); names = new Dictionary(StringComparer.OrdinalIgnoreCase); entryCapacity = Math.Min(entryCapacity, (uint)entryOk.Count); for (int i = 0; i < entryCapacity; i++) { if (!entryOk[i]) continue; var pos = stream.ReadUInt32(); var streamId = stream.ReadUInt32(); nameData.Position = pos; var streamName = ReadCString(nameData); names[streamName] = streamId; } } } void ReadStringTable() { uint streamId; if (!names.TryGetValue("/names", out streamId)) throw new PdbException("String table not found"); var stream = streams[streamId].Content; stream.Position = 8; uint strSize = stream.ReadUInt32(); using (var strData = stream.Create(stream.FileOffset + stream.Position, strSize)) { stream.Position += strSize; strings = new Dictionary(); uint count = stream.ReadUInt32(); for (uint i = 0; i < count; i++) { var pos = stream.ReadUInt32(); if (pos == 0) continue; strData.Position = pos; strings[pos] = ReadCString(strData); } } } static uint ReadSizeField(IBinaryReader reader) { int size = reader.ReadInt32(); return size <= 0 ? 0 : (uint)size; } ushort? ReadModules() { var stream = streams[STREAM_DBI].Content; stream.Position = 20; ushort symrecStream = stream.ReadUInt16(); stream.Position += 2; uint gpmodiSize = ReadSizeField(stream); // gpmodiSize uint otherSize = 0; otherSize += ReadSizeField(stream); // secconSize otherSize += ReadSizeField(stream); // secmapSize otherSize += ReadSizeField(stream); // filinfSize otherSize += ReadSizeField(stream); // tsmapSize stream.ReadUInt32(); // mfcIndex uint dbghdrSize = ReadSizeField(stream); otherSize += ReadSizeField(stream); // ecinfoSize stream.Position += 8; modules = new List(); using (var moduleStream = stream.Create((FileOffset)stream.Position, gpmodiSize)) { while (moduleStream.Position < moduleStream.Length) { var module = new DbiModule(); module.Read(moduleStream); modules.Add(module); } } if (IsValidStreamIndex(symrecStream)) ReadGlobalSymbols(streams[symrecStream].Content); if (dbghdrSize != 0) { stream.Position += gpmodiSize; stream.Position += otherSize; stream.Position += 12; return stream.ReadUInt16(); } return null; } internal DbiDocument GetDocument(uint nameId) { var name = strings[nameId]; DbiDocument doc; if (!documents.TryGetValue(name, out doc)) { doc = new DbiDocument(name); uint streamId; if (names.TryGetValue("/src/files/" + name, out streamId)) doc.Read(streams[streamId].Content); documents.Add(name, doc); } return doc; } void ReadGlobalSymbols(IImageStream stream) { stream.Position = 0; while (stream.Position < stream.Length) { var size = stream.ReadUInt16(); var begin = stream.Position; var end = begin + size; if ((SymbolType)stream.ReadUInt16() == SymbolType.S_PUB32) { stream.Position += 4; var offset = stream.ReadUInt32(); stream.Position += 2; var name = ReadCString(stream); if (name == "COM+_Entry_Point") { entryPt = offset; break; } } stream.Position = end; } } void ApplyRidMap(IImageStream stream) { stream.Position = 0; var map = new uint[stream.Length / 4]; for (int i = 0; i < map.Length; i++) map[i] = stream.ReadUInt32(); foreach (var module in modules) { foreach (var func in module.Functions) { var rid = (uint)func.Token & 0x00ffffff; rid = map[rid]; func.token = (int)((func.Token & 0xff000000) | rid); } } if (entryPt != 0) { var rid = entryPt & 0x00ffffff; rid = map[rid]; entryPt = (entryPt & 0xff000000) | rid; } } internal static string ReadCString(IImageStream stream) { var bytes = stream.ReadBytesUntilByte(0); if (bytes == null) return string.Empty; var value = Encoding.UTF8.GetString(bytes); stream.Position++; return value; } public override SymbolMethod GetMethod(MethodDef method, int version) { DbiFunction symMethod; if (functions.TryGetValue(method.MDToken.ToInt32(), out symMethod)) return symMethod; return null; } public override IList Documents { get { if (documentsResult == null) { var docs = new SymbolDocument[documents.Count]; int i = 0; foreach (var doc in documents.Values) docs[i++] = doc; documentsResult = docs; } return documentsResult; } } volatile SymbolDocument[] documentsResult; public override int UserEntryPoint { get { return (int)entryPt; } } internal void GetCustomDebugInfos(DbiFunction symMethod, MethodDef method, CilBody body, IList result) { const string CDI_NAME = "MD2"; var asyncMethod = PseudoCustomDebugInfoFactory.TryCreateAsyncMethod(method.Module, method, body, symMethod.AsyncKickoffMethod, symMethod.AsyncStepInfos, symMethod.AsyncCatchHandlerILOffset); if (asyncMethod != null) result.Add(asyncMethod); var cdiData = symMethod.Root.GetSymAttribute(CDI_NAME); if (cdiData == null) return; PdbCustomDebugInfoReader.Read(method, body, result, cdiData); } public override void GetCustomDebugInfos(int token, GenericParamContext gpContext, IList result) { } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/SymbolReaderCreator.cs000066400000000000000000000037571325033663500236650ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using dnlib.DotNet.Pdb.Symbols; using dnlib.IO; namespace dnlib.DotNet.Pdb.Managed { /// /// Creates a instance /// static class SymbolReaderCreator { /// /// Creates a new instance /// /// Path to assembly /// A new instance or null if there's no PDB /// file. public static SymbolReader CreateFromAssemblyFile(string assemblyFileName) { return Create(Path.ChangeExtension(assemblyFileName, "pdb")); } /// /// Creates a new instance /// /// Path to PDB file /// A new instance or null if there's no PDB /// file on disk. public static SymbolReader Create(string pdbFileName) { return Create(ImageStreamUtils.OpenImageStream(pdbFileName)); } /// /// Creates a new instance /// /// PDB file data /// A new instance or null. public static SymbolReader Create(byte[] pdbData) { return Create(MemoryImageStream.Create(pdbData)); } /// /// Creates a new instance /// /// PDB file stream which is now owned by this method /// A new instance or null. public static SymbolReader Create(IImageStream pdbStream) { if (pdbStream == null) return null; try { var pdbReader = new PdbReader(); pdbReader.Read(pdbStream); return pdbReader; } catch (PdbException) { } catch (IOException) { } finally { if (pdbStream != null) pdbStream.Dispose(); } return null; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Managed/SymbolType.cs000066400000000000000000000113331325033663500220510ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Pdb.Managed { enum SymbolType : ushort { S_COMPILE = 0x0001, S_REGISTER_16t = 0x0002, S_CONSTANT_16t = 0x0003, S_UDT_16t = 0x0004, S_SSEARCH = 0x0005, S_END = 0x0006, S_SKIP = 0x0007, S_CVRESERVE = 0x0008, S_OBJNAME_ST = 0x0009, S_ENDARG = 0x000A, S_COBOLUDT_16t = 0x000B, S_MANYREG_16t = 0x000C, S_RETURN = 0x000D, S_ENTRYTHIS = 0x000E, S_BPREL16 = 0x0100, S_LDATA16 = 0x0101, S_GDATA16 = 0x0102, S_PUB16 = 0x0103, S_LPROC16 = 0x0104, S_GPROC16 = 0x0105, S_THUNK16 = 0x0106, S_BLOCK16 = 0x0107, S_WITH16 = 0x0108, S_LABEL16 = 0x0109, S_CEXMODEL16 = 0x010A, S_VFTABLE16 = 0x010B, S_REGREL16 = 0x010C, S_BPREL32_16t = 0x0200, S_LDATA32_16t = 0x0201, S_GDATA32_16t = 0x0202, S_PUB32_16t = 0x0203, S_LPROC32_16t = 0x0204, S_GPROC32_16t = 0x0205, S_THUNK32_ST = 0x0206, S_BLOCK32_ST = 0x0207, S_WITH32_ST = 0x0208, S_LABEL32_ST = 0x0209, S_CEXMODEL32 = 0x020A, S_VFTABLE32_16t = 0x020B, S_REGREL32_16t = 0x020C, S_LTHREAD32_16t = 0x020D, S_GTHREAD32_16t = 0x020E, S_SLINK32 = 0x020F, S_LPROCMIPS_16t = 0x0300, S_GPROCMIPS_16t = 0x0301, S_PROCREF_ST = 0x0400, S_DATAREF_ST = 0x0401, S_ALIGN = 0x0402, S_LPROCREF_ST = 0x0403, S_OEM = 0x0404, S_TI16_MAX = 0x1000, S_REGISTER_ST = 0x1001, S_CONSTANT_ST = 0x1002, S_UDT_ST = 0x1003, S_COBOLUDT_ST = 0x1004, S_MANYREG_ST = 0x1005, S_BPREL32_ST = 0x1006, S_LDATA32_ST = 0x1007, S_GDATA32_ST = 0x1008, S_PUB32_ST = 0x1009, S_LPROC32_ST = 0x100A, S_GPROC32_ST = 0x100B, S_VFTABLE32 = 0x100C, S_REGREL32_ST = 0x100D, S_LTHREAD32_ST = 0x100E, S_GTHREAD32_ST = 0x100F, S_LPROCMIPS_ST = 0x1010, S_GPROCMIPS_ST = 0x1011, S_FRAMEPROC = 0x1012, S_COMPILE2_ST = 0x1013, S_MANYREG2_ST = 0x1014, S_LPROCIA64_ST = 0x1015, S_GPROCIA64_ST = 0x1016, S_LOCALSLOT_ST = 0x1017, S_PARAMSLOT_ST = 0x1018, S_ANNOTATION = 0x1019, S_GMANPROC_ST = 0x101A, S_LMANPROC_ST = 0x101B, S_RESERVED1 = 0x101C, S_RESERVED2 = 0x101D, S_RESERVED3 = 0x101E, S_RESERVED4 = 0x101F, S_LMANDATA_ST = 0x1020, S_GMANDATA_ST = 0x1021, S_MANFRAMEREL_ST = 0x1022, S_MANREGISTER_ST = 0x1023, S_MANSLOT_ST = 0x1024, S_MANMANYREG_ST = 0x1025, S_MANREGREL_ST = 0x1026, S_MANMANYREG2_ST = 0x1027, S_MANTYPREF = 0x1028, S_UNAMESPACE_ST = 0x1029, S_ST_MAX = 0x1100, S_OBJNAME = 0x1101, S_THUNK32 = 0x1102, S_BLOCK32 = 0x1103, S_WITH32 = 0x1104, S_LABEL32 = 0x1105, S_REGISTER = 0x1106, S_CONSTANT = 0x1107, S_UDT = 0x1108, S_COBOLUDT = 0x1109, S_MANYREG = 0x110A, S_BPREL32 = 0x110B, S_LDATA32 = 0x110C, S_GDATA32 = 0x110D, S_PUB32 = 0x110E, S_LPROC32 = 0x110F, S_GPROC32 = 0x1110, S_REGREL32 = 0x1111, S_LTHREAD32 = 0x1112, S_GTHREAD32 = 0x1113, S_LPROCMIPS = 0x1114, S_GPROCMIPS = 0x1115, S_COMPILE2 = 0x1116, S_MANYREG2 = 0x1117, S_LPROCIA64 = 0x1118, S_GPROCIA64 = 0x1119, S_LOCALSLOT = 0x111A, S_PARAMSLOT = 0x111B, S_LMANDATA = 0x111C, S_GMANDATA = 0x111D, S_MANFRAMEREL = 0x111E, S_MANREGISTER = 0x111F, S_MANSLOT = 0x1120, S_MANMANYREG = 0x1121, S_MANREGREL = 0x1122, S_MANMANYREG2 = 0x1123, S_UNAMESPACE = 0x1124, S_PROCREF = 0x1125, S_DATAREF = 0x1126, S_LPROCREF = 0x1127, S_ANNOTATIONREF = 0x1128, S_TOKENREF = 0x1129, S_GMANPROC = 0x112A, S_LMANPROC = 0x112B, S_TRAMPOLINE = 0x112C, S_MANCONSTANT = 0x112D, S_ATTR_FRAMEREL = 0x112E, S_ATTR_REGISTER = 0x112F, S_ATTR_REGREL = 0x1130, S_ATTR_MANYREG = 0x1131, S_SEPCODE = 0x1132, S_LOCAL_2005 = 0x1133, S_DEFRANGE_2005 = 0x1134, S_DEFRANGE2_2005 = 0x1135, S_SECTION = 0x1136, S_COFFGROUP = 0x1137, S_EXPORT = 0x1138, S_CALLSITEINFO = 0x1139, S_FRAMECOOKIE = 0x113A, S_DISCARDED = 0x113B, S_COMPILE3 = 0x113C, S_ENVBLOCK = 0x113D, S_LOCAL = 0x113E, S_DEFRANGE = 0x113F, S_DEFRANGE_SUBFIELD = 0x1140, S_DEFRANGE_REGISTER = 0x1141, S_DEFRANGE_FRAMEPOINTER_REL = 0x1142, S_DEFRANGE_SUBFIELD_REGISTER = 0x1143, S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE = 0x1144, S_DEFRANGE_REGISTER_REL = 0x1145, S_LPROC32_ID = 0x1146, S_GPROC32_ID = 0x1147, S_LPROCMIPS_ID = 0x1148, S_GPROCMIPS_ID = 0x1149, S_LPROCIA64_ID = 0x114A, S_GPROCIA64_ID = 0x114B, S_BUILDINFO = 0x114C, S_INLINESITE = 0x114D, S_INLINESITE_END = 0x114E, S_PROC_ID_END = 0x114F, S_DEFRANGE_HLSL = 0x1150, S_GDATA_HLSL = 0x1151, S_LDATA_HLSL = 0x1152, S_FILESTATIC = 0x1153, S_LOCAL_DPC_GROUPSHARED = 0x1154, S_LPROC32_DPC = 0x1155, S_LPROC32_DPC_ID = 0x1156, S_DEFRANGE_DPC_PTR_TAG = 0x1157, S_DPC_SYM_TAG_MAP = 0x1158, S_ARMSWITCHTABLE = 0x1159, S_CALLEES = 0x115A, S_CALLERS = 0x115B, S_POGODATA = 0x115C, S_INLINESITE2 = 0x115D, S_HEAPALLOCSITE = 0x115E, S_RECTYPE_MAX, } }dnlib-2.1_VS2010/src/DotNet/Pdb/ManagedSymbolReaderCreator.cs000066400000000000000000000031451325033663500235750ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb.Symbols; using dnlib.IO; namespace dnlib.DotNet.Pdb { static class ManagedSymbolReaderCreator { public static SymbolReader CreateFromAssemblyFile(IMetaData metaData, string assemblyFileName) { return Create(metaData, Path.ChangeExtension(assemblyFileName, "pdb")); } public static SymbolReader Create(IMetaData metaData, string pdbFileName) { return Create(metaData, ImageStreamUtils.OpenImageStream(pdbFileName)); } public static SymbolReader Create(IMetaData metaData, byte[] pdbData) { return Create(metaData, MemoryImageStream.Create(pdbData)); } public static SymbolReader Create(IMetaData metaData, IImageStream pdbStream) { try { // Embedded pdbs have priority var res = Create(metaData); if (res != null) { if (pdbStream != null) pdbStream.Dispose(); return res; } return CreateCore(pdbStream); } catch { if (pdbStream != null) pdbStream.Dispose(); throw; } } static SymbolReader CreateCore(IImageStream pdbStream) { if (pdbStream == null) return null; try { uint sig = pdbStream.ReadUInt32(); pdbStream.Position = 0; if (sig == 0x424A5342) return Portable.SymbolReaderCreator.TryCreate(pdbStream, false); return Managed.SymbolReaderCreator.Create(pdbStream); } catch (IOException) { } if (pdbStream != null) pdbStream.Dispose(); return null; } internal static SymbolReader Create(IMetaData metaData) { return Portable.SymbolReaderCreator.TryCreate(metaData); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/PdbConstant.cs000066400000000000000000000040471325033663500206310ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet.Pdb { /// /// A constant in a method scope, eg. "const int SomeConstant = 123;" /// public sealed class PdbConstant : IHasCustomDebugInformation { string name; TypeSig type; object value; /// /// Gets/sets the name /// public string Name { get { return name; } set { name = value; } } /// /// Gets/sets the type of the constant /// public TypeSig Type { get { return type; } set { type = value; } } /// /// Gets/sets the value of the constant /// public object Value { get { return value; } set { this.value = value; } } /// /// Constructor /// public PdbConstant() { } /// /// Constructor /// /// Name of constant /// Type of constant /// Constant value public PdbConstant(string name, TypeSig type, object value) { this.name = name; this.type = type; this.value = value; } /// public int HasCustomDebugInformationTag { get { return 25; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { return customDebugInfos; } } readonly ThreadSafe.IList customDebugInfos = ThreadSafeListCreator.Create(); /// /// ToString() /// /// public override string ToString() { var type = Type; return (type == null ? "" : type.ToString()) + " " + Name + " = " + (Value == null ? "null" : Value.ToString() + " (" + Value.GetType().FullName + ")"); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/PdbCustomDebugInfo.cs000066400000000000000000000721721325033663500221010ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.DotNet.Emit; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet.Pdb { /// /// Custom debug info kind /// /// See CustomDebugInfoKind in Roslyn source code public enum PdbCustomDebugInfoKind { /// /// /// UsingGroups, /// /// /// ForwardMethodInfo, /// /// /// ForwardModuleInfo, /// /// /// StateMachineHoistedLocalScopes, /// /// /// StateMachineTypeName, /// /// /// DynamicLocals, /// /// /// EditAndContinueLocalSlotMap, /// /// /// EditAndContinueLambdaMap, /// /// /// TupleElementNames, // Values 0x00-0xFF are reserved for Windows PDB CDIs. /// /// Unknown /// Unknown = int.MinValue, /// /// /// TupleElementNames_PortablePdb, /// /// /// DefaultNamespace, /// /// /// DynamicLocalVariables, /// /// /// EmbeddedSource, /// /// /// SourceLink, /// /// /// AsyncMethod, /// /// /// IteratorMethod, } /// /// Base class of custom debug info added to the PDB file by the compiler /// public abstract class PdbCustomDebugInfo { /// /// Gets the custom debug info kind /// public abstract PdbCustomDebugInfoKind Kind { get; } /// /// Gets the custom debug info guid, see /// public abstract Guid Guid { get; } } /// /// Unknown custom debug info. If you see an instance of this class, you're using an old dnlib version or /// dnlib hasn't been updated to support this new custom debug info kind. /// public sealed class PdbUnknownCustomDebugInfo : PdbCustomDebugInfo { readonly PdbCustomDebugInfoKind kind; readonly Guid guid; readonly byte[] data; /// /// Gets the custom debug info kind /// public override PdbCustomDebugInfoKind Kind { get { return kind; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return guid; } } /// /// Gets the data /// public byte[] Data { get { return data; } } /// /// Constructor /// /// Custom debug info kind /// Raw custom debug info data public PdbUnknownCustomDebugInfo(PdbCustomDebugInfoKind kind, byte[] data) { if (data == null) throw new ArgumentNullException("data"); this.kind = kind; this.data = data; guid = Guid.Empty; } /// /// Constructor /// /// Custom debug info guid /// Raw custom debug info data public PdbUnknownCustomDebugInfo(Guid guid, byte[] data) { if (data == null) throw new ArgumentNullException("data"); this.kind = PdbCustomDebugInfoKind.Unknown; this.data = data; this.guid = guid; } } /// /// Contains sizes of using groups /// public sealed class PdbUsingGroupsCustomDebugInfo : PdbCustomDebugInfo { readonly ThreadSafe.IList usingCounts; /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.UsingGroups; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return Guid.Empty; } } /// /// Gets the using counts /// public ThreadSafe.IList UsingCounts { get { return usingCounts; } } /// /// Constructor /// public PdbUsingGroupsCustomDebugInfo() { usingCounts = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Initial capacity of public PdbUsingGroupsCustomDebugInfo(int capacity) { usingCounts = ThreadSafeListCreator.Create(capacity); } } /// /// Contains a reference to another method that contains the import strings /// public sealed class PdbForwardMethodInfoCustomDebugInfo : PdbCustomDebugInfo { IMethodDefOrRef method; /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.ForwardMethodInfo; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return Guid.Empty; } } /// /// Gets/sets the referenced method /// public IMethodDefOrRef Method { get { return method; } set { method = value; } } /// /// Constructor /// public PdbForwardMethodInfoCustomDebugInfo() { } /// /// Constructor /// /// The referenced method public PdbForwardMethodInfoCustomDebugInfo(IMethodDefOrRef method) { this.method = method; } } /// /// Contains a reference to another method that contains the per-module debug info (assembly reference aliases) /// public sealed class PdbForwardModuleInfoCustomDebugInfo : PdbCustomDebugInfo { IMethodDefOrRef method; /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.ForwardModuleInfo; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return Guid.Empty; } } /// /// Gets/sets the referenced method /// public IMethodDefOrRef Method { get { return method; } set { method = value; } } /// /// Constructor /// public PdbForwardModuleInfoCustomDebugInfo() { } /// /// Constructor /// /// The referenced method public PdbForwardModuleInfoCustomDebugInfo(IMethodDefOrRef method) { this.method = method; } } /// /// State machine hosted local scope info /// public struct StateMachineHoistedLocalScope { /// /// true if it's a syntesized local ( and are both null) /// public bool IsSynthesizedLocal { get { return Start == null && End == null; } } /// /// The instruction of the first operation in the scope. Can be null if it's a synthesized local /// public Instruction Start; /// /// The instruction of the first operation outside of the scope or null if it ends at the last instruction in the body. /// Can also be null if it's a synthesized local (in which case is also null, see ) /// public Instruction End; /// /// Constructor /// /// Start of the scope /// First instruction after the end of the scope public StateMachineHoistedLocalScope(Instruction start, Instruction end) { Start = start; End = end; } } /// /// Contains local scopes for state machine hoisted local variables. /// public sealed class PdbStateMachineHoistedLocalScopesCustomDebugInfo : PdbCustomDebugInfo { readonly ThreadSafe.IList scopes; /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.StateMachineHoistedLocalScopes; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return CustomDebugInfoGuids.StateMachineHoistedLocalScopes; } } /// /// Gets the scopes /// public ThreadSafe.IList Scopes { get { return scopes; } } /// /// Constructor /// public PdbStateMachineHoistedLocalScopesCustomDebugInfo() { scopes = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Initial capacity of public PdbStateMachineHoistedLocalScopesCustomDebugInfo(int capacity) { scopes = ThreadSafeListCreator.Create(capacity); } } /// /// Contains the state machine type /// public sealed class PdbStateMachineTypeNameCustomDebugInfo : PdbCustomDebugInfo { /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.StateMachineTypeName; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return Guid.Empty; } } /// /// Gets/sets the state machine type /// public TypeDef Type { get; set; } /// /// Constructor /// public PdbStateMachineTypeNameCustomDebugInfo() { } /// /// Constructor /// /// State machine type public PdbStateMachineTypeNameCustomDebugInfo(TypeDef type) { Type = type; } } /// /// Contains dynamic flags for local variables and constants /// public sealed class PdbDynamicLocalsCustomDebugInfo : PdbCustomDebugInfo { readonly ThreadSafe.IList locals; /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.DynamicLocals; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return Guid.Empty; } } /// /// Gets the dynamic locals /// public ThreadSafe.IList Locals { get { return locals; } } /// /// Constructor /// public PdbDynamicLocalsCustomDebugInfo() { locals = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Initial capacity of public PdbDynamicLocalsCustomDebugInfo(int capacity) { locals = ThreadSafeListCreator.Create(capacity); } } /// /// Dynamic local info /// public sealed class PdbDynamicLocal { readonly ThreadSafe.IList flags; string name; Local local; /// /// Gets the dynamic flags /// public ThreadSafe.IList Flags { get { return flags; } } /// /// Gets/sets the name of the local. The name must have at most 64 characters and no char can be NUL (0x0000). /// If null is written, is returned instead. /// public string Name { get { var n = name; if (n != null) return n; var l = local; return l == null ? null : l.Name; } set { name = value; } } /// /// true if it's a constant and not a variable ( is null) /// public bool IsConstant { get { return Local == null; } } /// /// true if it's a variable ( is not null) /// public bool IsVariable { get { return Local != null; } } /// /// Gets/sets the local. Could be null if there's no local (it's a 'const' local). /// public Local Local { get { return local; } set { local = value; } } /// /// Constructor /// public PdbDynamicLocal() { flags = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Initial capacity of public PdbDynamicLocal(int capacity) { flags = ThreadSafeListCreator.Create(capacity); } } /// /// Contains the EnC local variable slot map /// public sealed class PdbEditAndContinueLocalSlotMapCustomDebugInfo : PdbCustomDebugInfo { readonly byte[] data; /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.EditAndContinueLocalSlotMap; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return CustomDebugInfoGuids.EncLocalSlotMap; } } /// /// Gets the data. Spec: https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PortablePdb-Metadata.md#EditAndContinueLocalSlotMap /// public byte[] Data { get { return data; } } /// /// Constructor /// /// Raw custom debug info data public PdbEditAndContinueLocalSlotMapCustomDebugInfo(byte[] data) { if (data == null) throw new ArgumentNullException("data"); this.data = data; } } /// /// Contains the EnC lambda map /// public sealed class PdbEditAndContinueLambdaMapCustomDebugInfo : PdbCustomDebugInfo { readonly byte[] data; /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.EditAndContinueLambdaMap; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return CustomDebugInfoGuids.EncLambdaAndClosureMap; } } /// /// Gets the data. Spec: https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PortablePdb-Metadata.md#EditAndContinueLambdaAndClosureMap /// public byte[] Data { get { return data; } } /// /// Constructor /// /// Raw custom debug info data public PdbEditAndContinueLambdaMapCustomDebugInfo(byte[] data) { if (data == null) throw new ArgumentNullException("data"); this.data = data; } } /// /// Contains tuple element names for local variables and constants /// public sealed class PdbTupleElementNamesCustomDebugInfo : PdbCustomDebugInfo { readonly ThreadSafe.IList names; /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.TupleElementNames; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return Guid.Empty; } } /// /// Gets the tuple element names /// public ThreadSafe.IList Names { get { return names; } } /// /// Constructor /// public PdbTupleElementNamesCustomDebugInfo() { names = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Initial capacity of public PdbTupleElementNamesCustomDebugInfo(int capacity) { names = ThreadSafeListCreator.Create(capacity); } } /// /// Tuple element name info /// public sealed class PdbTupleElementNames { readonly ThreadSafe.IList tupleElementNames; string name; Local local; Instruction scopeStart, scopeEnd; /// /// Gets/sets the name of the local. If null is written, is returned instead. /// public string Name { get { var n = name; if (n != null) return n; var l = local; return l == null ? null : l.Name; } set { name = value; } } /// /// Gets/sets the local. It's null if it's a constant, and non-null if it's a variable /// public Local Local { get { return local; } set { local = value; } } /// /// true if it's a constant. Constants have a scope ( and ) /// public bool IsConstant { get { return local == null; } } /// /// true if it's a variable. Variables don't have a scope ( and ) /// public bool IsVariable { get { return local != null; } } /// /// Gets/sets the start of the scope or null. Only constants have a scope. /// public Instruction ScopeStart { get { return scopeStart; } set { scopeStart = value; } } /// /// Gets/sets the end of the scope or null if it has no scope or if the scope ends at the end of the body. Only constants have a scope. /// public Instruction ScopeEnd { get { return scopeEnd; } set { scopeEnd = value; } } /// /// Gets the tuple element names /// public ThreadSafe.IList TupleElementNames { get { return tupleElementNames; } } /// /// Constructor /// public PdbTupleElementNames() { tupleElementNames = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Initial capacity of public PdbTupleElementNames(int capacity) { tupleElementNames = ThreadSafeListCreator.Create(capacity); } } /// /// Contains tuple element names for local variables and constants /// public sealed class PortablePdbTupleElementNamesCustomDebugInfo : PdbCustomDebugInfo { readonly ThreadSafe.IList names; /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.TupleElementNames_PortablePdb; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return CustomDebugInfoGuids.TupleElementNames; } } /// /// Gets the tuple element names /// public ThreadSafe.IList Names { get { return names; } } /// /// Constructor /// public PortablePdbTupleElementNamesCustomDebugInfo() { names = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Initial capacity of public PortablePdbTupleElementNamesCustomDebugInfo(int capacity) { names = ThreadSafeListCreator.Create(capacity); } } /// /// Async method stepping info /// /// It's internal and translated to a /// sealed class PdbAsyncMethodSteppingInformationCustomDebugInfo : PdbCustomDebugInfo { readonly ThreadSafe.IList asyncStepInfos; /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.Unknown; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return CustomDebugInfoGuids.AsyncMethodSteppingInformationBlob; } } /// /// Gets the catch handler instruction or null /// public Instruction CatchHandler { get; set; } /// /// Gets all async step infos /// public ThreadSafe.IList AsyncStepInfos { get { return asyncStepInfos; } } /// /// Constructor /// public PdbAsyncMethodSteppingInformationCustomDebugInfo() { asyncStepInfos = ThreadSafeListCreator.Create(); } } /// /// Default namespace /// public sealed class PdbDefaultNamespaceCustomDebugInfo : PdbCustomDebugInfo { /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.DefaultNamespace; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return CustomDebugInfoGuids.DefaultNamespace; } } /// /// Gets the default namespace /// public string Namespace { get; set; } /// /// Constructor /// public PdbDefaultNamespaceCustomDebugInfo() { } /// /// Constructor /// /// Default namespace public PdbDefaultNamespaceCustomDebugInfo(string defaultNamespace) { Namespace = defaultNamespace; } } /// /// Dynamic flags /// public sealed class PdbDynamicLocalVariablesCustomDebugInfo : PdbCustomDebugInfo { /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.DynamicLocalVariables; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return CustomDebugInfoGuids.DynamicLocalVariables; } } /// /// Gets/sets the dynamic flags /// public bool[] Flags { get; set; } /// /// Constructor /// public PdbDynamicLocalVariablesCustomDebugInfo() { } /// /// Constructor /// /// Dynamic flags public PdbDynamicLocalVariablesCustomDebugInfo(bool[] flags) { Flags = flags; } } /// /// Contains the source code /// public sealed class PdbEmbeddedSourceCustomDebugInfo : PdbCustomDebugInfo { /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.EmbeddedSource; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return CustomDebugInfoGuids.EmbeddedSource; } } /// /// Gets the source code blob. /// /// It's not decompressed and converted to a string because the encoding isn't specified. /// /// https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PortablePdb-Metadata.md#embedded-source-c-and-vb-compilers /// public byte[] SourceCodeBlob { get; set; } /// /// Constructor /// public PdbEmbeddedSourceCustomDebugInfo() { } /// /// Constructor /// /// Source code blob public PdbEmbeddedSourceCustomDebugInfo(byte[] sourceCodeBlob) { SourceCodeBlob = sourceCodeBlob; } } /// /// Contains the source link file /// public sealed class PdbSourceLinkCustomDebugInfo : PdbCustomDebugInfo { /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.SourceLink; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return CustomDebugInfoGuids.SourceLink; } } /// /// Gets the source link file contents /// public byte[] SourceLinkBlob { get; set; } /// /// Constructor /// public PdbSourceLinkCustomDebugInfo() { } /// /// Constructor /// /// Source link file contents public PdbSourceLinkCustomDebugInfo(byte[] sourceLinkBlob) { SourceLinkBlob = sourceLinkBlob; } } /// /// Async method info /// public sealed class PdbAsyncMethodCustomDebugInfo : PdbCustomDebugInfo { /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.AsyncMethod; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return Guid.Empty; } } readonly ThreadSafe.IList asyncStepInfos; /// /// Gets/sets the starting method that initiates the async operation /// public MethodDef KickoffMethod { get; set; } /// /// Gets/sets the instruction for the compiler generated catch handler that wraps an async method. /// This can be null. /// public Instruction CatchHandlerInstruction { get; set; } /// /// Gets all step infos used by the debugger /// public ThreadSafe.IList StepInfos { get { return asyncStepInfos; } } /// /// Constructor /// public PdbAsyncMethodCustomDebugInfo() { asyncStepInfos = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Default capacity for public PdbAsyncMethodCustomDebugInfo(int stepInfosCapacity) { asyncStepInfos = ThreadSafeListCreator.Create(stepInfosCapacity); } } /// /// Async step info used by debuggers /// public struct PdbAsyncStepInfo { /// /// The yield instruction /// public Instruction YieldInstruction; /// /// Resume method /// public MethodDef BreakpointMethod; /// /// Resume instruction (where the debugger puts a breakpoint) /// public Instruction BreakpointInstruction; /// /// Constructor /// /// The yield instruction /// Resume method /// Resume instruction (where the debugger puts a breakpoint) public PdbAsyncStepInfo(Instruction yieldInstruction, MethodDef breakpointMethod, Instruction breakpointInstruction) { YieldInstruction = yieldInstruction; BreakpointMethod = breakpointMethod; BreakpointInstruction = breakpointInstruction; } } /// /// Iterator method /// public sealed class PdbIteratorMethodCustomDebugInfo : PdbCustomDebugInfo { /// /// Returns /// public override PdbCustomDebugInfoKind Kind { get { return PdbCustomDebugInfoKind.IteratorMethod; } } /// /// Gets the custom debug info guid, see /// public override Guid Guid { get { return Guid.Empty; } } /// /// Gets the kickoff method /// public MethodDef KickoffMethod { get; set; } /// /// Constructor /// public PdbIteratorMethodCustomDebugInfo() { } /// /// Constructor /// /// Kickoff method public PdbIteratorMethodCustomDebugInfo(MethodDef kickoffMethod) { KickoffMethod = kickoffMethod; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/PdbDocument.cs000066400000000000000000000071261325033663500206170ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using dnlib.DotNet.Pdb.Symbols; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet.Pdb { /// /// A PDB document /// [DebuggerDisplay("{Url}")] public sealed class PdbDocument : IHasCustomDebugInformation { /// /// Gets/sets the document URL /// public string Url { get; set; } /// /// Gets/sets the language GUID. See /// public Guid Language { get; set; } /// /// Gets/sets the language vendor GUID. See /// public Guid LanguageVendor { get; set; } /// /// Gets/sets the document type GUID. See /// public Guid DocumentType { get; set; } /// /// Gets/sets the checksum algorithm ID. See /// public Guid CheckSumAlgorithmId { get; set; } /// /// Gets/sets the checksum /// public byte[] CheckSum { get; set; } /// public int HasCustomDebugInformationTag { get { return 22; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { return customDebugInfos; } } readonly ThreadSafe.IList customDebugInfos = ThreadSafeListCreator.Create(); /// /// Default constructor /// public PdbDocument() { } /// /// Constructor /// /// A instance public PdbDocument(SymbolDocument symDoc) { if (symDoc == null) throw new ArgumentNullException("symDoc"); this.Url = symDoc.URL; this.Language = symDoc.Language; this.LanguageVendor = symDoc.LanguageVendor; this.DocumentType = symDoc.DocumentType; this.CheckSumAlgorithmId = symDoc.CheckSumAlgorithmId; this.CheckSum = symDoc.CheckSum; foreach (var cdi in symDoc.CustomDebugInfos) customDebugInfos.Add(cdi); } /// /// Constructor /// /// Document URL /// Language. See /// Language vendor. See /// Document type. See /// Checksum algorithm ID. See /// Checksum public PdbDocument(string url, Guid language, Guid languageVendor, Guid documentType, Guid checkSumAlgorithmId, byte[] checkSum) { this.Url = url; this.Language = language; this.LanguageVendor = languageVendor; this.DocumentType = documentType; this.CheckSumAlgorithmId = checkSumAlgorithmId; this.CheckSum = checkSum; } /// public override int GetHashCode() { return (Url ?? string.Empty).ToUpperInvariant().GetHashCode(); } /// public override bool Equals(object obj) { var other = obj as PdbDocument; if (other == null) return false; return (Url ?? string.Empty).Equals(other.Url ?? string.Empty, StringComparison.OrdinalIgnoreCase); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/PdbDocumentConstants.cs000066400000000000000000000020441325033663500225060ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet.Pdb { /// /// PDB document constants /// public static class PdbDocumentConstants { #pragma warning disable 1591 // Missing XML comment for publicly visible type or member public static readonly Guid LanguageCSharp = new Guid("3F5162F8-07C6-11D3-9053-00C04FA302A1"); public static readonly Guid LanguageVisualBasic = new Guid("3A12D0B8-C26C-11D0-B442-00A0244A1DD2"); public static readonly Guid LanguageFSharp = new Guid("AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3"); public static readonly Guid HashSHA1 = new Guid("FF1816EC-AA5E-4D10-87F7-6F4963833460"); public static readonly Guid HashSHA256 = new Guid("8829D00F-11B8-4213-878B-770E8597AC16"); public static readonly Guid LanguageVendorMicrosoft = new Guid("994B45C4-E6E9-11D2-903F-00C04FA302A1"); public static readonly Guid DocumentTypeText = new Guid("5A869D0B-6611-11D3-BD2A-0000F80849BD"); #pragma warning restore 1591 // Missing XML comment for publicly visible type or member } } dnlib-2.1_VS2010/src/DotNet/Pdb/PdbFileKind.cs000066400000000000000000000005651325033663500205260ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Pdb { /// /// PDB file kind /// public enum PdbFileKind { /// /// Windows PDB /// WindowsPDB, /// /// Portable PDB /// PortablePDB, /// /// Embedded portable PDB /// EmbeddedPortablePDB, } } dnlib-2.1_VS2010/src/DotNet/Pdb/PdbImplType.cs000066400000000000000000000013261325033663500206000ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Pdb { /// /// PDB implementation type /// public enum PdbImplType { /// /// Use Microsoft's COM DLL (diasymreader.dll). It's not recommended to use this reader since it can only be accessed on the COM thread. /// /// This reader can only read the old PDB files (aka Windows PDB files). It does not support portable PDB files. /// MicrosoftCOM, /// /// Use the managed PDB reader. It supports Windows PDB files and portable PDB files and is the default PDB reader. /// Managed, /// /// Use the default PDB reader /// Default = Managed, } } dnlib-2.1_VS2010/src/DotNet/Pdb/PdbImport.cs000066400000000000000000000271511325033663500203130ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Diagnostics; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet.Pdb { /// /// Import scope /// public sealed class PdbImportScope : IHasCustomDebugInformation { readonly ThreadSafe.IList imports = ThreadSafeListCreator.Create(); /// /// Constructor /// public PdbImportScope() { } /// /// Gets/sets the parent import scope /// public PdbImportScope Parent { get; set; } /// /// Gets all imports /// public ThreadSafe.IList Imports { get { return imports; } } /// /// true if is not empty /// public bool HasImports { get { return imports.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 26; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { return customDebugInfos; } } readonly ThreadSafe.IList customDebugInfos = ThreadSafeListCreator.Create(); } /// /// Import kind /// public enum PdbImportDefinitionKind { #pragma warning disable 1591 // Missing XML comment for publicly visible type or member ImportNamespace, ImportAssemblyNamespace, ImportType, ImportXmlNamespace, ImportAssemblyReferenceAlias, AliasAssemblyReference, AliasNamespace, AliasAssemblyNamespace, AliasType, #pragma warning restore 1591 // Missing XML comment for publicly visible type or member } /// /// PDB import base class /// public abstract class PdbImport { /// /// Gets the import kind /// public abstract PdbImportDefinitionKind Kind { get; } internal abstract void PreventNewClasses(); } /// /// Import namespace /// [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbImportNamespace : PdbImport { /// /// Returns /// public sealed override PdbImportDefinitionKind Kind { get { return PdbImportDefinitionKind.ImportNamespace; } } /// /// Gets the target namespace /// public string TargetNamespace { get; set; } /// /// Constructor /// public PdbImportNamespace() { } /// /// Constructor /// /// public PdbImportNamespace(string targetNamespace) { TargetNamespace = targetNamespace; } internal sealed override void PreventNewClasses() { } string GetDebuggerString() { return string.Format("{0}: {1}", Kind, TargetNamespace); } } /// /// Import assembly, namespace /// [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbImportAssemblyNamespace : PdbImport { /// /// Returns /// public sealed override PdbImportDefinitionKind Kind { get { return PdbImportDefinitionKind.ImportAssemblyNamespace; } } /// /// Gets the target assembly /// public AssemblyRef TargetAssembly { get; set; } /// /// Gets the target namespace /// public string TargetNamespace { get; set; } /// /// Constructor /// public PdbImportAssemblyNamespace() { } /// /// Constructor /// /// /// public PdbImportAssemblyNamespace(AssemblyRef targetAssembly, string targetNamespace) { TargetAssembly = targetAssembly; TargetNamespace = targetNamespace; } internal sealed override void PreventNewClasses() { } string GetDebuggerString() { return string.Format("{0}: {1} {2}", Kind, TargetAssembly, TargetNamespace); } } /// /// Import type /// [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbImportType : PdbImport { /// /// Returns /// public sealed override PdbImportDefinitionKind Kind { get { return PdbImportDefinitionKind.ImportType; } } /// /// Gets the target type /// public ITypeDefOrRef TargetType { get; set; } /// /// Constructor /// public PdbImportType() { } /// /// Constructor /// /// public PdbImportType(ITypeDefOrRef targetType) { TargetType = targetType; } internal sealed override void PreventNewClasses() { } string GetDebuggerString() { return string.Format("{0}: {1}", Kind, TargetType); } } /// /// Import xml namespace /// [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbImportXmlNamespace : PdbImport { /// /// Returns /// public sealed override PdbImportDefinitionKind Kind { get { return PdbImportDefinitionKind.ImportXmlNamespace; } } /// /// Gets the alias /// public string Alias { get; set; } /// /// Gets the target namespace /// public string TargetNamespace { get; set; } /// /// Constructor /// public PdbImportXmlNamespace() { } /// /// Constructor /// /// /// public PdbImportXmlNamespace(string alias, string targetNamespace) { Alias = alias; TargetNamespace = targetNamespace; } internal sealed override void PreventNewClasses() { } string GetDebuggerString() { return string.Format("{0}: {1} = {2}", Kind, Alias, TargetNamespace); } } /// /// Import assembly reference alias /// [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbImportAssemblyReferenceAlias : PdbImport { /// /// Returns /// public sealed override PdbImportDefinitionKind Kind { get { return PdbImportDefinitionKind.ImportAssemblyReferenceAlias; } } /// /// Gets the alias /// public string Alias { get; set; } /// /// Constructor /// public PdbImportAssemblyReferenceAlias() { } /// /// Constructor /// /// public PdbImportAssemblyReferenceAlias(string alias) { Alias = alias; } internal sealed override void PreventNewClasses() { } string GetDebuggerString() { return string.Format("{0}: {1}", Kind, Alias); } } /// /// Alias assembly reference /// [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbAliasAssemblyReference : PdbImport { /// /// Returns /// public sealed override PdbImportDefinitionKind Kind { get { return PdbImportDefinitionKind.AliasAssemblyReference; } } /// /// Gets the alias /// public string Alias { get; set; } /// /// Gets the target assembly /// public AssemblyRef TargetAssembly { get; set; } /// /// Constructor /// public PdbAliasAssemblyReference() { } /// /// Constructor /// /// /// public PdbAliasAssemblyReference(string alias, AssemblyRef targetAssembly) { Alias = alias; TargetAssembly = targetAssembly; } internal sealed override void PreventNewClasses() { } string GetDebuggerString() { return string.Format("{0}: {1} = {2}", Kind, Alias, TargetAssembly); } } /// /// Alias namespace /// [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbAliasNamespace : PdbImport { /// /// Returns /// public sealed override PdbImportDefinitionKind Kind { get { return PdbImportDefinitionKind.AliasNamespace; } } /// /// Gets the alias /// public string Alias { get; set; } /// /// Gets the target namespace /// public string TargetNamespace { get; set; } /// /// Constructor /// public PdbAliasNamespace() { } /// /// Constructor /// /// /// public PdbAliasNamespace(string alias, string targetNamespace) { Alias = alias; TargetNamespace = targetNamespace; } internal sealed override void PreventNewClasses() { } string GetDebuggerString() { return string.Format("{0}: {1} = {2}", Kind, Alias, TargetNamespace); } } /// /// Alias assembly namespace /// [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbAliasAssemblyNamespace : PdbImport { /// /// Returns /// public sealed override PdbImportDefinitionKind Kind { get { return PdbImportDefinitionKind.AliasAssemblyNamespace; } } /// /// Gets the alias /// public string Alias { get; set; } /// /// Gets the target assembly /// public AssemblyRef TargetAssembly { get; set; } /// /// Gets the target namespace /// public string TargetNamespace { get; set; } /// /// Constructor /// public PdbAliasAssemblyNamespace() { } /// /// Constructor /// /// /// /// public PdbAliasAssemblyNamespace(string alias, AssemblyRef targetAssembly, string targetNamespace) { Alias = alias; TargetAssembly = targetAssembly; TargetNamespace = targetNamespace; } internal sealed override void PreventNewClasses() { } string GetDebuggerString() { return string.Format("{0}: {1} = {2} {3}", Kind, Alias, TargetAssembly, TargetNamespace); } } /// /// Alias type /// [DebuggerDisplay("{GetDebuggerString(),nq}")] public sealed class PdbAliasType : PdbImport { /// /// Returns /// public sealed override PdbImportDefinitionKind Kind { get { return PdbImportDefinitionKind.AliasType; } } /// /// Gets the alias /// public string Alias { get; set; } /// /// Gets the target type /// public ITypeDefOrRef TargetType { get; set; } /// /// Constructor /// public PdbAliasType() { } /// /// Constructor /// /// /// public PdbAliasType(string alias, ITypeDefOrRef targetType) { Alias = alias; TargetType = targetType; } internal sealed override void PreventNewClasses() { } string GetDebuggerString() { return string.Format("{0}: {1} = {2}", Kind, Alias, TargetType); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/PdbLocal.cs000066400000000000000000000040361325033663500200700ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.DotNet.Emit; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet.Pdb { /// /// A local variable /// public sealed class PdbLocal : IHasCustomDebugInformation { /// /// Constructor /// public PdbLocal() { } /// /// Constructor /// /// /// /// public PdbLocal(Local local, string name, PdbLocalAttributes attributes) { Local = local; Name = name; Attributes = attributes; } /// /// Gets/sets the local /// public Local Local { get; set; } /// /// Gets/sets the name /// public string Name { get; set; } /// /// Gets/sets the attributes /// public PdbLocalAttributes Attributes { get; set; } /// /// Gets the index of the local /// public int Index { get { return Local.Index; } } /// /// true if it should be hidden in debugger variables windows. Not all compiler generated locals have this flag set. /// public bool IsDebuggerHidden { get { return (Attributes & PdbLocalAttributes.DebuggerHidden) != 0; } set { if (value) Attributes |= PdbLocalAttributes.DebuggerHidden; else Attributes &= ~PdbLocalAttributes.DebuggerHidden; } } /// public int HasCustomDebugInformationTag { get { return 24; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { return customDebugInfos; } } readonly ThreadSafe.IList customDebugInfos = ThreadSafeListCreator.Create(); } } dnlib-2.1_VS2010/src/DotNet/Pdb/PdbLocalAttributes.cs000066400000000000000000000006671325033663500221450ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet.Pdb { /// /// Local attributes /// [Flags] public enum PdbLocalAttributes { /// /// No bit is set /// None = 0, /// /// Local should be hidden in debugger variables windows. Not all compiler generated locals have this flag set. /// DebuggerHidden = 0x00000001, } } dnlib-2.1_VS2010/src/DotNet/Pdb/PdbMethod.cs000066400000000000000000000006461325033663500202610ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Pdb { /// /// A PDB method /// public sealed class PdbMethod { /// /// Gets/sets the root scope. It contains all scopes of the method, using namespaces, variables and constants /// public PdbScope Scope { get; set; } /// /// Constructor /// public PdbMethod() { } } } dnlib-2.1_VS2010/src/DotNet/Pdb/PdbScope.cs000066400000000000000000000060201325033663500201020ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Diagnostics; using dnlib.DotNet.Emit; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet.Pdb { /// /// A PDB scope /// [DebuggerDisplay("{Start} - {End}")] public sealed class PdbScope : IHasCustomDebugInformation { readonly ThreadSafe.IList scopes = ThreadSafeListCreator.Create(); readonly ThreadSafe.IList locals = ThreadSafeListCreator.Create(); readonly ThreadSafe.IList namespaces = ThreadSafeListCreator.Create(); readonly ThreadSafe.IList constants = ThreadSafeListCreator.Create(); /// /// Constructor /// public PdbScope() { } /// /// Gets/sets the first instruction /// public Instruction Start { get; set; } /// /// Gets/sets the last instruction. It's null if it ends at the end of the method. /// public Instruction End { get; set; } /// /// Gets all child scopes /// public ThreadSafe.IList Scopes { get { return scopes; } } /// /// true if is not empty /// public bool HasScopes { get { return scopes.Count > 0; } } /// /// Gets all locals in this scope /// public ThreadSafe.IList Variables { get { return locals; } } /// /// true if is not empty /// public bool HasVariables { get { return locals.Count > 0; } } /// /// Gets all namespaces (Windows PDBs). Portable PDBs use /// public ThreadSafe.IList Namespaces { get { return namespaces; } } /// /// true if is not empty /// public bool HasNamespaces { get { return namespaces.Count > 0; } } /// /// Gets/sets the import scope (Portable PDBs). Windows PDBs use /// public PdbImportScope ImportScope { get; set; } /// /// Gets all constants /// public ThreadSafe.IList Constants { get { return constants; } } /// /// true if is not empty /// public bool HasConstants { get { return constants.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 23; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { return customDebugInfos; } } readonly ThreadSafe.IList customDebugInfos = ThreadSafeListCreator.Create(); } } dnlib-2.1_VS2010/src/DotNet/Pdb/PdbState.cs000066400000000000000000000313621325033663500201200ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using dnlib.DotNet.Emit; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb.Symbols; using dnlib.Threading; namespace dnlib.DotNet.Pdb { /// /// PDB state for a /// public sealed class PdbState { readonly SymbolReader reader; readonly Dictionary docDict = new Dictionary(); MethodDef userEntryPoint; readonly Compiler compiler; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// /// Gets/sets the PDB file kind. You can change it from portable PDB to embedded portable PDB /// and vice versa. Converting a Windows PDB to a portable PDB isn't supported. /// public PdbFileKind PdbFileKind { get; set; } /// /// Gets/sets the user entry point method. /// public MethodDef UserEntryPoint { get { return userEntryPoint; } set { userEntryPoint = value; } } /// /// Gets all PDB documents /// public IEnumerable Documents { get { #if THREAD_SAFE theLock.EnterWriteLock(); try { return new List(docDict.Values); } finally { theLock.ExitWriteLock(); } #else return docDict.Values; #endif } } /// /// true if is not empty /// public bool HasDocuments { get { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif return docDict.Count > 0; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Constructor /// /// Module /// PDB file kind public PdbState(ModuleDef module, PdbFileKind pdbFileKind) { if (module == null) throw new ArgumentNullException("module"); this.compiler = CalculateCompiler(module); PdbFileKind = pdbFileKind; } /// /// Constructor /// /// A instance /// Owner module public PdbState(SymbolReader reader, ModuleDefMD module) { if (reader == null) throw new ArgumentNullException("reader"); if (module == null) throw new ArgumentNullException("module"); this.reader = reader; reader.Initialize(module); PdbFileKind = reader.PdbFileKind; this.compiler = CalculateCompiler(module); this.userEntryPoint = module.ResolveToken(reader.UserEntryPoint) as MethodDef; foreach (var doc in reader.Documents) Add_NoLock(new PdbDocument(doc)); } /// /// Adds /// /// New document /// if it wasn't inserted, or the already existing document /// if it was already inserted. public PdbDocument Add(PdbDocument doc) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif return Add_NoLock(doc); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } PdbDocument Add_NoLock(PdbDocument doc) { PdbDocument orig; if (docDict.TryGetValue(doc, out orig)) return orig; docDict.Add(doc, doc); return doc; } /// /// Removes /// /// Document /// true if it was removed, false if it wasn't inserted. public bool Remove(PdbDocument doc) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif return docDict.Remove(doc); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Returns an inserted instance or null if it's not been /// inserted yet. /// /// A PDB document /// The existing or null if it doesn't exist. public PdbDocument GetExisting(PdbDocument doc) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif PdbDocument orig; docDict.TryGetValue(doc, out orig); return orig; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Removes all documents /// /// public void RemoveAllDocuments() { RemoveAllDocuments(false); } /// /// Removes all documents and optionally returns them /// /// true if all the original s /// should be returned. /// All s if is true /// or null if is false. public List RemoveAllDocuments(bool returnDocs) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif var docs = returnDocs ? new List(docDict.Values) : null; docDict.Clear(); return docs; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } internal Compiler Compiler { get { return compiler; } } internal void InitializeMethodBody(ModuleDefMD module, MethodDef ownerMethod, CilBody body) { if (reader == null) return; var method = reader.GetMethod(ownerMethod, 1); if (method != null) { var pdbMethod = new PdbMethod(); pdbMethod.Scope = CreateScope(module, GenericParamContext.Create(ownerMethod), body, method.RootScope); AddSequencePoints(body, method); body.PdbMethod = pdbMethod; } } internal void InitializeCustomDebugInfos(MethodDef ownerMethod, CilBody body, IList customDebugInfos) { if (reader == null) return; var method = reader.GetMethod(ownerMethod, 1); if (method != null) method.GetCustomDebugInfos(ownerMethod, body, customDebugInfos); } static Compiler CalculateCompiler(ModuleDef module) { if (module == null) return Compiler.Other; foreach (var asmRef in module.GetAssemblyRefs()) { if (asmRef.Name == nameAssemblyVisualBasic) return Compiler.VisualBasic; } // The VB runtime can also be embedded, and if so, it seems that "Microsoft.VisualBasic.Embedded" // attribute is added to the assembly's custom attributes. var asm = module.Assembly; if (asm != null && asm.CustomAttributes.IsDefined("Microsoft.VisualBasic.Embedded")) return Compiler.VisualBasic; return Compiler.Other; } static readonly UTF8String nameAssemblyVisualBasic = new UTF8String("Microsoft.VisualBasic"); void AddSequencePoints(CilBody body, SymbolMethod method) { int instrIndex = 0; foreach (var sp in method.SequencePoints) { var instr = GetInstruction(body.Instructions, sp.Offset, ref instrIndex); if (instr == null) continue; var seqPoint = new SequencePoint() { Document = Add_NoLock(new PdbDocument(sp.Document)), StartLine = sp.Line, StartColumn = sp.Column, EndLine = sp.EndLine, EndColumn = sp.EndColumn, }; instr.SequencePoint = seqPoint; } } struct CreateScopeState { public SymbolScope SymScope; public PdbScope PdbScope; public IList Children; public int ChildrenIndex; } PdbScope CreateScope(ModuleDefMD module, GenericParamContext gpContext, CilBody body, SymbolScope symScope) { if (symScope == null) return null; // Don't use recursive calls var stack = new Stack(); var state = new CreateScopeState() { SymScope = symScope }; recursive_call: int instrIndex = 0; int endIsInclusiveValue = Compiler == Compiler.VisualBasic ? 1 : 0; state.PdbScope = new PdbScope() { Start = GetInstruction(body.Instructions, state.SymScope.StartOffset, ref instrIndex), End = GetInstruction(body.Instructions, state.SymScope.EndOffset + endIsInclusiveValue, ref instrIndex), }; foreach (var cdi in state.SymScope.CustomDebugInfos) state.PdbScope.CustomDebugInfos.Add(cdi); foreach (var symLocal in state.SymScope.Locals) { int localIndex = symLocal.Index; if ((uint)localIndex >= (uint)body.Variables.Count) { // VB sometimes creates a PDB local without a metadata local continue; } var local = body.Variables[localIndex]; var name = symLocal.Name; local.SetName(name); var attributes = symLocal.Attributes; local.SetAttributes(attributes); var pdbLocal = new PdbLocal(local, name, attributes); foreach (var cdi in symLocal.CustomDebugInfos) pdbLocal.CustomDebugInfos.Add(cdi); state.PdbScope.Variables.Add(pdbLocal); } foreach (var ns in state.SymScope.Namespaces) state.PdbScope.Namespaces.Add(ns.Name); state.PdbScope.ImportScope = state.SymScope.ImportScope; var constants = state.SymScope.GetConstants(module, gpContext); for (int i = 0; i < constants.Count; i++) { var constant = constants[i]; var type = constant.Type.RemovePinnedAndModifiers(); if (type != null) { // Fix a few values since they're stored as some other type in the PDB switch (type.ElementType) { case ElementType.Boolean: if (constant.Value is short) constant.Value = (short)constant.Value != 0; break; case ElementType.Char: if (constant.Value is ushort) constant.Value = (char)(ushort)constant.Value; break; case ElementType.I1: if (constant.Value is short) constant.Value = (sbyte)(short)constant.Value; break; case ElementType.U1: if (constant.Value is short) constant.Value = (byte)(short)constant.Value; break; case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.Void: case ElementType.Ptr: case ElementType.ByRef: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.FnPtr: case ElementType.ValueType: break; case ElementType.String: if (PdbFileKind == PdbFileKind.WindowsPDB) { // "" is stored as null, and null is stored as (int)0 if (constant.Value is int && (int)constant.Value == 0) constant.Value = null; else if (constant.Value == null) constant.Value = string.Empty; } else Debug.Assert(PdbFileKind == PdbFileKind.PortablePDB || PdbFileKind == PdbFileKind.EmbeddedPortablePDB); break; case ElementType.Object: case ElementType.Class: case ElementType.SZArray: case ElementType.Array: default: if (constant.Value is int && (int)constant.Value == 0) constant.Value = null; break; case ElementType.GenericInst: var gis = (GenericInstSig)type; if (gis.GenericType is ValueTypeSig) break; goto case ElementType.Class; case ElementType.Var: case ElementType.MVar: var gp = ((GenericSig)type).GenericParam; if (gp != null) { if (gp.HasNotNullableValueTypeConstraint) break; if (gp.HasReferenceTypeConstraint) goto case ElementType.Class; } break; } } state.PdbScope.Constants.Add(constant); } // Here's the now somewhat obfuscated for loop state.ChildrenIndex = 0; state.Children = state.SymScope.Children; do_return: if (state.ChildrenIndex < state.Children.Count) { var child = state.Children[state.ChildrenIndex]; stack.Push(state); state = new CreateScopeState() { SymScope = child }; goto recursive_call; } if (stack.Count == 0) return state.PdbScope; // Return from recursive call, and execute the last part of the for loop var newPdbScope = state.PdbScope; state = stack.Pop(); state.PdbScope.Scopes.Add(newPdbScope); state.ChildrenIndex++; goto do_return; } static Instruction GetInstruction(IList instrs, int offset, ref int index) { if (instrs.Count > 0 && offset > instrs[instrs.Count - 1].Offset) return null; for (int i = index; i < instrs.Count; i++) { var instr = instrs[i]; if (instr.Offset < offset) continue; if (instr.Offset == offset) { index = i; return instr; } break; } for (int i = 0; i < index; i++) { var instr = instrs[i]; if (instr.Offset < offset) continue; if (instr.Offset == offset) { index = i; return instr; } break; } return null; } internal void InitializeCustomDebugInfos(MDToken token, GenericParamContext gpContext, IList result) { Debug.Assert(token.Table != Table.Method, "Methods get initialized when reading the method bodies"); if (reader != null) reader.GetCustomDebugInfos(token.ToInt32(), gpContext, result); } internal void Dispose() { if (reader != null) reader.Dispose(); } } enum Compiler { Other, VisualBasic, } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/000077500000000000000000000000001325033663500176265ustar00rootroot00000000000000dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/DocumentNameReader.cs000066400000000000000000000054431325033663500236650ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Text; using dnlib.DotNet.MD; using dnlib.IO; namespace dnlib.DotNet.Pdb.Portable { struct DocumentNameReader { const int MAX_NAME_LENGTH = 64 * 1024; readonly Dictionary docNamePartDict; readonly BlobStream blobStream; readonly StringBuilder sb; char[] prevSepChars; int prevSepCharsLength; byte[] prevSepCharBytes; int prevSepCharBytesCount; public DocumentNameReader(BlobStream blobStream) { docNamePartDict = new Dictionary(); this.blobStream = blobStream; sb = new StringBuilder(); prevSepChars = new char[2]; prevSepCharsLength = 0; prevSepCharBytes = new byte[3]; prevSepCharBytesCount = 0; } public string ReadDocumentName(uint offset) { sb.Length = 0; using (var stream = blobStream.CreateStream(offset)) { int sepCharsLength; var sepChars = ReadSeparatorChar(stream, out sepCharsLength); bool needSep = false; while (stream.Position < stream.Length) { if (needSep) sb.Append(sepChars, 0, sepCharsLength); needSep = !(sepCharsLength == 1 && sepChars[0] == '\0'); var part = ReadDocumentNamePart(stream.ReadCompressedUInt32()); sb.Append(part); if (sb.Length > MAX_NAME_LENGTH) { sb.Length = MAX_NAME_LENGTH; break; } } } return sb.ToString(); } string ReadDocumentNamePart(uint offset) { string name; if (docNamePartDict.TryGetValue(offset, out name)) return name; var data = blobStream.ReadNoNull(offset); name = Encoding.UTF8.GetString(data); docNamePartDict.Add(offset, name); return name; } char[] ReadSeparatorChar(IImageStream stream, out int charLength) { if (prevSepCharBytesCount != 0 && prevSepCharBytesCount <= stream.Length) { var pos = stream.Position; bool ok = true; for (int i = 0; i < prevSepCharBytesCount; i++) { if (i >= prevSepCharBytes.Length || stream.ReadByte() != prevSepCharBytes[i]) { ok = false; break; } } if (ok) { charLength = prevSepCharsLength; return prevSepChars; } stream.Position = pos; } var decoder = Encoding.UTF8.GetDecoder(); var bytes = new byte[1]; prevSepCharBytesCount = 0; for (int i = 0; ; i++) { byte b = stream.ReadByte(); prevSepCharBytesCount++; if (i == 0 && b == 0) break; if (i < prevSepCharBytes.Length) prevSepCharBytes[i] = b; bytes[0] = b; bool isLastByte = stream.Position + 1 == stream.Length; int bytesUsed; bool completed; decoder.Convert(bytes, 0, 1, prevSepChars, 0, prevSepChars.Length, isLastByte, out bytesUsed, out prevSepCharsLength, out completed); if (prevSepCharsLength > 0) break; } charLength = prevSepCharsLength; return prevSepChars; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/ImportDefinitionKindUtils.cs000066400000000000000000000037311325033663500252730ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Diagnostics; namespace dnlib.DotNet.Pdb.Portable { static class ImportDefinitionKindUtils { public const PdbImportDefinitionKind UNKNOWN_IMPORT_KIND = (PdbImportDefinitionKind)(-1); public static PdbImportDefinitionKind ToPdbImportDefinitionKind(uint value) { // See System.Reflection.Metadata.ImportDefinitionKind switch (value) { case 1: return PdbImportDefinitionKind.ImportNamespace; case 2: return PdbImportDefinitionKind.ImportAssemblyNamespace; case 3: return PdbImportDefinitionKind.ImportType; case 4: return PdbImportDefinitionKind.ImportXmlNamespace; case 5: return PdbImportDefinitionKind.ImportAssemblyReferenceAlias; case 6: return PdbImportDefinitionKind.AliasAssemblyReference; case 7: return PdbImportDefinitionKind.AliasNamespace; case 8: return PdbImportDefinitionKind.AliasAssemblyNamespace; case 9: return PdbImportDefinitionKind.AliasType; default: Debug.Fail("Unknown import definition kind: 0x" + value.ToString("X")); return UNKNOWN_IMPORT_KIND; } } public static bool ToImportDefinitionKind(PdbImportDefinitionKind kind, out uint rawKind) { switch (kind) { case PdbImportDefinitionKind.ImportNamespace: rawKind = 1; return true; case PdbImportDefinitionKind.ImportAssemblyNamespace: rawKind = 2; return true; case PdbImportDefinitionKind.ImportType: rawKind = 3; return true; case PdbImportDefinitionKind.ImportXmlNamespace: rawKind = 4; return true; case PdbImportDefinitionKind.ImportAssemblyReferenceAlias: rawKind = 5; return true; case PdbImportDefinitionKind.AliasAssemblyReference: rawKind = 6; return true; case PdbImportDefinitionKind.AliasNamespace: rawKind = 7; return true; case PdbImportDefinitionKind.AliasAssemblyNamespace: rawKind = 8; return true; case PdbImportDefinitionKind.AliasType: rawKind = 9; return true; default: rawKind = uint.MaxValue; return false; } } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/ImportScopeBlobReader.cs000066400000000000000000000114451325033663500243500ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Diagnostics; using System.Text; using dnlib.DotNet.MD; using dnlib.IO; namespace dnlib.DotNet.Pdb.Portable { // https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PortablePdb-Metadata.md#imports-blob struct ImportScopeBlobReader { readonly ModuleDef module; readonly BlobStream blobStream; /// /// Constructor /// /// Module that resolves assembly and type references /// Portable PDB blob stream public ImportScopeBlobReader(ModuleDef module, BlobStream blobStream) { this.module = module; this.blobStream = blobStream; } public void Read(uint imports, IList result) { if (imports == 0) return; using (var stream = blobStream.CreateStream(imports)) { while (stream.Position < stream.Length) { var kind = ImportDefinitionKindUtils.ToPdbImportDefinitionKind(stream.ReadCompressedUInt32()); string targetNamespace, alias; AssemblyRef targetAssembly; PdbImport import; ITypeDefOrRef targetType; switch (kind) { case PdbImportDefinitionKind.ImportNamespace: // ::= ImportNamespace targetNamespace = ReadUTF8(stream.ReadCompressedUInt32()); import = new PdbImportNamespace(targetNamespace); break; case PdbImportDefinitionKind.ImportAssemblyNamespace: // ::= ImportAssemblyNamespace targetAssembly = TryReadAssemblyRef(stream.ReadCompressedUInt32()); targetNamespace = ReadUTF8(stream.ReadCompressedUInt32()); import = new PdbImportAssemblyNamespace(targetAssembly, targetNamespace); break; case PdbImportDefinitionKind.ImportType: // ::= ImportType targetType = TryReadType(stream.ReadCompressedUInt32()); import = new PdbImportType(targetType); break; case PdbImportDefinitionKind.ImportXmlNamespace: // ::= ImportXmlNamespace alias = ReadUTF8(stream.ReadCompressedUInt32()); targetNamespace = ReadUTF8(stream.ReadCompressedUInt32()); import = new PdbImportXmlNamespace(alias, targetNamespace); break; case PdbImportDefinitionKind.ImportAssemblyReferenceAlias: // ::= ImportReferenceAlias alias = ReadUTF8(stream.ReadCompressedUInt32()); import = new PdbImportAssemblyReferenceAlias(alias); break; case PdbImportDefinitionKind.AliasAssemblyReference: // ::= AliasAssemblyReference alias = ReadUTF8(stream.ReadCompressedUInt32()); targetAssembly = TryReadAssemblyRef(stream.ReadCompressedUInt32()); import = new PdbAliasAssemblyReference(alias, targetAssembly); break; case PdbImportDefinitionKind.AliasNamespace: // ::= AliasNamespace alias = ReadUTF8(stream.ReadCompressedUInt32()); targetNamespace = ReadUTF8(stream.ReadCompressedUInt32()); import = new PdbAliasNamespace(alias, targetNamespace); break; case PdbImportDefinitionKind.AliasAssemblyNamespace: // ::= AliasAssemblyNamespace alias = ReadUTF8(stream.ReadCompressedUInt32()); targetAssembly = TryReadAssemblyRef(stream.ReadCompressedUInt32()); targetNamespace = ReadUTF8(stream.ReadCompressedUInt32()); import = new PdbAliasAssemblyNamespace(alias, targetAssembly, targetNamespace); break; case PdbImportDefinitionKind.AliasType: // ::= AliasType alias = ReadUTF8(stream.ReadCompressedUInt32()); targetType = TryReadType(stream.ReadCompressedUInt32()); import = new PdbAliasType(alias, targetType); break; case ImportDefinitionKindUtils.UNKNOWN_IMPORT_KIND: import = null; break; default: Debug.Fail("Unknown import definition kind: " + kind.ToString()); import = null; break; } if (import != null) result.Add(import); } Debug.Assert(stream.Position == stream.Length); } } ITypeDefOrRef TryReadType(uint codedToken) { uint token; bool b = CodedToken.TypeDefOrRef.Decode(codedToken, out token); Debug.Assert(b); if (!b) return null; var type = module.ResolveToken(token) as ITypeDefOrRef; Debug.Assert(type != null); return type; } AssemblyRef TryReadAssemblyRef(uint rid) { var asmRef = module.ResolveToken(0x23000000 + rid) as AssemblyRef; Debug.Assert(asmRef != null); return asmRef; } string ReadUTF8(uint offset) { var bytes = blobStream.ReadNoNull(offset); return Encoding.UTF8.GetString(bytes); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/ImportScopeBlobWriter.cs000066400000000000000000000111051325033663500244130ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.IO; using System.Text; using dnlib.DotNet.Writer; namespace dnlib.DotNet.Pdb.Portable { // https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PortablePdb-Metadata.md#imports-blob struct ImportScopeBlobWriter { readonly IWriterError helper; readonly MetaData systemMetaData; readonly BlobHeap blobHeap; ImportScopeBlobWriter(IWriterError helper, MetaData systemMetaData, BlobHeap blobHeap) { this.helper = helper; this.systemMetaData = systemMetaData; this.blobHeap = blobHeap; } public static void Write(IWriterError helper, MetaData systemMetaData, BinaryWriter writer, BlobHeap blobHeap, IList imports) { var blobWriter = new ImportScopeBlobWriter(helper, systemMetaData, blobHeap); blobWriter.Write(writer, imports); } uint WriteUTF8(string s) { if (s == null) { helper.Error("String is null"); s = string.Empty; } var bytes = Encoding.UTF8.GetBytes(s); return blobHeap.Add(bytes); } void Write(BinaryWriter writer, IList imports) { foreach (var import in imports) { uint rawKind; if (!ImportDefinitionKindUtils.ToImportDefinitionKind(import.Kind, out rawKind)) { helper.Error("Unknown import definition kind: " + import.Kind.ToString()); return; } writer.WriteCompressedUInt32(rawKind); switch (import.Kind) { case PdbImportDefinitionKind.ImportNamespace: // ::= ImportNamespace writer.WriteCompressedUInt32(WriteUTF8(((PdbImportNamespace)import).TargetNamespace)); break; case PdbImportDefinitionKind.ImportAssemblyNamespace: // ::= ImportAssemblyNamespace writer.WriteCompressedUInt32(systemMetaData.GetToken(((PdbImportAssemblyNamespace)import).TargetAssembly).Rid); writer.WriteCompressedUInt32(WriteUTF8(((PdbImportAssemblyNamespace)import).TargetNamespace)); break; case PdbImportDefinitionKind.ImportType: // ::= ImportType writer.WriteCompressedUInt32(GetTypeDefOrRefEncodedToken(((PdbImportType)import).TargetType)); break; case PdbImportDefinitionKind.ImportXmlNamespace: // ::= ImportXmlNamespace writer.WriteCompressedUInt32(WriteUTF8(((PdbImportXmlNamespace)import).Alias)); writer.WriteCompressedUInt32(WriteUTF8(((PdbImportXmlNamespace)import).TargetNamespace)); break; case PdbImportDefinitionKind.ImportAssemblyReferenceAlias: // ::= ImportReferenceAlias writer.WriteCompressedUInt32(WriteUTF8(((PdbImportAssemblyReferenceAlias)import).Alias)); break; case PdbImportDefinitionKind.AliasAssemblyReference: // ::= AliasAssemblyReference writer.WriteCompressedUInt32(WriteUTF8(((PdbAliasAssemblyReference)import).Alias)); writer.WriteCompressedUInt32(systemMetaData.GetToken(((PdbAliasAssemblyReference)import).TargetAssembly).Rid); break; case PdbImportDefinitionKind.AliasNamespace: // ::= AliasNamespace writer.WriteCompressedUInt32(WriteUTF8(((PdbAliasNamespace)import).Alias)); writer.WriteCompressedUInt32(WriteUTF8(((PdbAliasNamespace)import).TargetNamespace)); break; case PdbImportDefinitionKind.AliasAssemblyNamespace: // ::= AliasAssemblyNamespace writer.WriteCompressedUInt32(WriteUTF8(((PdbAliasAssemblyNamespace)import).Alias)); writer.WriteCompressedUInt32(systemMetaData.GetToken(((PdbAliasAssemblyNamespace)import).TargetAssembly).Rid); writer.WriteCompressedUInt32(WriteUTF8(((PdbAliasAssemblyNamespace)import).TargetNamespace)); break; case PdbImportDefinitionKind.AliasType: // ::= AliasType writer.WriteCompressedUInt32(WriteUTF8(((PdbAliasType)import).Alias)); writer.WriteCompressedUInt32(GetTypeDefOrRefEncodedToken(((PdbAliasType)import).TargetType)); break; default: helper.Error("Unknown import definition kind: " + import.Kind.ToString()); return; } } } uint GetTypeDefOrRefEncodedToken(ITypeDefOrRef tdr) { if (tdr == null) { helper.Error("ITypeDefOrRef is null"); return 0; } var token = systemMetaData.GetToken(tdr); uint codedToken; if (MD.CodedToken.TypeDefOrRef.Encode(token, out codedToken)) return codedToken; helper.Error(string.Format("Could not encode token 0x{0:X8}", token.Raw)); return 0; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/ListCache.cs000066400000000000000000000010311325033663500220070ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Threading; namespace dnlib.DotNet.Pdb.Portable { static class ListCache { static volatile List cachedList; public static List AllocList() { return Interlocked.Exchange(ref cachedList, null) ?? new List(); } public static void Free(ref List list) { list.Clear(); cachedList = list; } public static T[] FreeAndToArray(ref List list) { var res = list.ToArray(); Free(ref list); return res; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/LocalConstantSigBlobReader.cs000066400000000000000000000163241325033663500253140ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.Text; using dnlib.IO; namespace dnlib.DotNet.Pdb.Portable { struct LocalConstantSigBlobReader { readonly ModuleDef module; readonly IImageStream reader; /*readonly*/ GenericParamContext gpContext; RecursionCounter recursionCounter; public LocalConstantSigBlobReader(ModuleDef module, IImageStream reader, GenericParamContext gpContext) { this.module = module; this.reader = reader; this.gpContext = gpContext; recursionCounter = default(RecursionCounter); } public bool Read(out TypeSig type, out object value) { try { return ReadCore(out type, out value); } catch { } type = null; value = null; return false; } bool ReadCore(out TypeSig type, out object value) { if (!recursionCounter.Increment()) { type = null; value = null; return false; } bool res; ITypeDefOrRef tdr; UTF8String ns, name; var et = (ElementType)reader.ReadByte(); switch (et) { case ElementType.Boolean: type = module.CorLibTypes.Boolean; value = reader.ReadBoolean(); if (reader.Position < reader.Length) type = ReadTypeDefOrRefSig(); res = true; break; case ElementType.Char: type = module.CorLibTypes.Char; value = (char)reader.ReadUInt16(); if (reader.Position < reader.Length) type = ReadTypeDefOrRefSig(); res = true; break; case ElementType.I1: type = module.CorLibTypes.SByte; value = reader.ReadSByte(); if (reader.Position < reader.Length) type = ReadTypeDefOrRefSig(); res = true; break; case ElementType.U1: type = module.CorLibTypes.Byte; value = reader.ReadByte(); if (reader.Position < reader.Length) type = ReadTypeDefOrRefSig(); res = true; break; case ElementType.I2: type = module.CorLibTypes.Int16; value = reader.ReadInt16(); if (reader.Position < reader.Length) type = ReadTypeDefOrRefSig(); res = true; break; case ElementType.U2: type = module.CorLibTypes.UInt16; value = reader.ReadUInt16(); if (reader.Position < reader.Length) type = ReadTypeDefOrRefSig(); res = true; break; case ElementType.I4: type = module.CorLibTypes.Int32; value = reader.ReadInt32(); if (reader.Position < reader.Length) type = ReadTypeDefOrRefSig(); res = true; break; case ElementType.U4: type = module.CorLibTypes.UInt32; value = reader.ReadUInt32(); if (reader.Position < reader.Length) type = ReadTypeDefOrRefSig(); res = true; break; case ElementType.I8: type = module.CorLibTypes.Int64; value = reader.ReadInt64(); if (reader.Position < reader.Length) type = ReadTypeDefOrRefSig(); res = true; break; case ElementType.U8: type = module.CorLibTypes.UInt64; value = reader.ReadUInt64(); if (reader.Position < reader.Length) type = ReadTypeDefOrRefSig(); res = true; break; case ElementType.R4: type = module.CorLibTypes.Single; value = reader.ReadSingle(); res = true; break; case ElementType.R8: type = module.CorLibTypes.Double; value = reader.ReadDouble(); res = true; break; case ElementType.String: type = module.CorLibTypes.String; value = ReadString(); res = true; break; case ElementType.Ptr: res = Read(out type, out value); if (res) type = new PtrSig(type); break; case ElementType.ByRef: res = Read(out type, out value); if (res) type = new ByRefSig(type); break; case ElementType.Object: type = module.CorLibTypes.Object; value = null; res = true; break; case ElementType.ValueType: tdr = ReadTypeDefOrRef(); type = tdr.ToTypeSig(); value = null; if (GetName(tdr, out ns, out name) && ns == stringSystem && tdr.DefinitionAssembly.IsCorLib()) { if (name == stringDecimal) { if (reader.Length - reader.Position != 13) goto default; try { byte b = reader.ReadByte(); value = new Decimal(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(), (b & 0x80) != 0, (byte)(b & 0x7F)); } catch { goto default; } } else if (name == stringDateTime) { if (reader.Length - reader.Position != 8) goto default; try { value = new DateTime(reader.ReadInt64()); } catch { goto default; } } } if (value == null && reader.Position != reader.Length) value = reader.ReadRemainingBytes(); res = true; break; case ElementType.Class: type = new ClassSig(ReadTypeDefOrRef()); value = reader.Position == reader.Length ? null : reader.ReadRemainingBytes(); res = true; break; case ElementType.CModReqd: tdr = ReadTypeDefOrRef(); res = Read(out type, out value); if (res) type = new CModReqdSig(tdr, type); break; case ElementType.CModOpt: tdr = ReadTypeDefOrRef(); res = Read(out type, out value); if (res) type = new CModOptSig(tdr, type); break; case ElementType.Var: case ElementType.Array: case ElementType.GenericInst: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.FnPtr: case ElementType.SZArray: case ElementType.MVar: case ElementType.End: case ElementType.Void: case ElementType.ValueArray: case ElementType.R: case ElementType.Internal: case ElementType.Module: case ElementType.Sentinel: case ElementType.Pinned: default: Debug.Fail("Unsupported element type in LocalConstant sig blob: " + et.ToString()); res = false; type = null; value = null; break; } recursionCounter.Decrement(); return res; } static readonly UTF8String stringSystem = new UTF8String("System"); static readonly UTF8String stringDecimal = new UTF8String("Decimal"); static readonly UTF8String stringDateTime = new UTF8String("DateTime"); static bool GetName(ITypeDefOrRef tdr, out UTF8String @namespace, out UTF8String name) { var tr = tdr as TypeRef; if (tr != null) { @namespace = tr.Namespace; name = tr.Name; return true; } var td = tdr as TypeDef; if (td != null) { @namespace = td.Namespace; name = td.Name; return true; } @namespace = null; name = null; return false; } TypeSig ReadTypeDefOrRefSig() { uint codedToken; if (!reader.ReadCompressedUInt32(out codedToken)) return null; ISignatureReaderHelper helper = module; var tdr = helper.ResolveTypeDefOrRef(codedToken, gpContext); return tdr.ToTypeSig(); } ITypeDefOrRef ReadTypeDefOrRef() { uint codedToken; if (!reader.ReadCompressedUInt32(out codedToken)) return null; ISignatureReaderHelper helper = module; var tdr = helper.ResolveTypeDefOrRef(codedToken, gpContext); var corType = module.CorLibTypes.GetCorLibTypeSig(tdr); if (corType != null) return corType.TypeDefOrRef; return tdr; } string ReadString() { if (reader.Position == reader.Length) return string.Empty; byte b = reader.ReadByte(); if (b == 0xFF && reader.Position == reader.Length) return null; reader.Position--; return Encoding.Unicode.GetString(reader.ReadRemainingBytes()); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/LocalConstantSigBlobWriter.cs000066400000000000000000000200521325033663500253570ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using System.Text; using dnlib.DotNet.Writer; namespace dnlib.DotNet.Pdb.Portable { struct LocalConstantSigBlobWriter { readonly IWriterError helper; readonly MetaData systemMetaData; LocalConstantSigBlobWriter(IWriterError helper, MetaData systemMetaData) { this.helper = helper; this.systemMetaData = systemMetaData; } public static void Write(IWriterError helper, MetaData systemMetaData, BinaryWriter writer, TypeSig type, object value) { var sigWriter = new LocalConstantSigBlobWriter(helper, systemMetaData); sigWriter.Write(writer, type, value); } void Write(BinaryWriter writer, TypeSig type, object value) { for (; ; type = type.Next) { if (type == null) return; var et = type.ElementType; writer.Write((byte)et); switch (et) { case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: WritePrimitiveValue(writer, et, value); return; case ElementType.R4: if (value is float) writer.Write((float)value); else { helper.Error("Expected a Single constant"); writer.Write((float)0); } return; case ElementType.R8: if (value is double) writer.Write((double)value); else { helper.Error("Expected a Double constant"); writer.Write((double)0); } return; case ElementType.String: if (value == null) writer.Write((byte)0xFF); else if (value is string) writer.Write(Encoding.Unicode.GetBytes((string)value)); else helper.Error("Expected a String constant"); return; case ElementType.Ptr: case ElementType.ByRef: WriteTypeDefOrRef(writer, new TypeSpecUser(type)); return; case ElementType.Object: return; case ElementType.ValueType: var tdr = ((ValueTypeSig)type).TypeDefOrRef; var td = tdr.ResolveTypeDef(); if (td == null) helper.Error(string.Format("Couldn't resolve type 0x{0:X8}", tdr == null ? 0 : tdr.MDToken.Raw)); else if (td.IsEnum) { var underlyingType = td.GetEnumUnderlyingType().RemovePinnedAndModifiers(); switch (underlyingType.GetElementType()) { case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: writer.BaseStream.Position--; writer.Write((byte)underlyingType.GetElementType()); WritePrimitiveValue(writer, underlyingType.GetElementType(), value); WriteTypeDefOrRef(writer, tdr); return; default: helper.Error("Invalid enum underlying type"); return; } } else { WriteTypeDefOrRef(writer, tdr); UTF8String ns, name; bool valueWritten = false; if (GetName(tdr, out ns, out name) && ns == stringSystem && tdr.DefinitionAssembly.IsCorLib()) { if (name == stringDecimal) { if (value is decimal) { var bits = decimal.GetBits((decimal)value); writer.Write((byte)((((uint)bits[3] >> 31) << 7) | (((uint)bits[3] >> 16) & 0x7F))); writer.Write(bits[0]); writer.Write(bits[1]); writer.Write(bits[2]); } else { helper.Error("Expected a Decimal constant"); writer.Write(new byte[13]); } valueWritten = true; } else if (name == stringDateTime) { if (value is DateTime) writer.Write(((DateTime)value).Ticks); else { helper.Error("Expected a DateTime constant"); writer.Write(0L); } valueWritten = true; } } if (!valueWritten) { if (value is byte[]) writer.Write((byte[])value); else if (value != null) { helper.Error("Unsupported constant: " + value.GetType().FullName); return; } } } return; case ElementType.Class: WriteTypeDefOrRef(writer, ((ClassSig)type).TypeDefOrRef); if (value is byte[]) writer.Write((byte[])value); else if (value != null) helper.Error("Expected a null constant"); return; case ElementType.CModReqd: case ElementType.CModOpt: WriteTypeDefOrRef(writer, ((ModifierSig)type).Modifier); break; case ElementType.Var: case ElementType.Array: case ElementType.GenericInst: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.FnPtr: case ElementType.SZArray: case ElementType.MVar: WriteTypeDefOrRef(writer, new TypeSpecUser(type)); return; case ElementType.End: case ElementType.Void: case ElementType.ValueArray: case ElementType.R: case ElementType.Internal: case ElementType.Module: case ElementType.Sentinel: case ElementType.Pinned: default: helper.Error("Unsupported element type in LocalConstant sig blob: " + et.ToString()); return; } } } static readonly UTF8String stringSystem = new UTF8String("System"); static readonly UTF8String stringDecimal = new UTF8String("Decimal"); static readonly UTF8String stringDateTime = new UTF8String("DateTime"); static bool GetName(ITypeDefOrRef tdr, out UTF8String @namespace, out UTF8String name) { var tr = tdr as TypeRef; if (tr != null) { @namespace = tr.Namespace; name = tr.Name; return true; } var td = tdr as TypeDef; if (td != null) { @namespace = td.Namespace; name = td.Name; return true; } @namespace = null; name = null; return false; } void WritePrimitiveValue(BinaryWriter writer, ElementType et, object value) { switch (et) { case ElementType.Boolean: if (value is bool) writer.Write((bool)value); else { helper.Error("Expected a Boolean constant"); writer.Write(false); } break; case ElementType.Char: if (value is char) writer.Write((ushort)(char)value); else { helper.Error("Expected a Char constant"); writer.Write((ushort)0); } break; case ElementType.I1: if (value is sbyte) writer.Write((sbyte)value); else { helper.Error("Expected a SByte constant"); writer.Write((sbyte)0); } break; case ElementType.U1: if (value is byte) writer.Write((byte)value); else { helper.Error("Expected a Byte constant"); writer.Write((byte)0); } break; case ElementType.I2: if (value is short) writer.Write((short)value); else { helper.Error("Expected an Int16 constant"); writer.Write((short)0); } break; case ElementType.U2: if (value is ushort) writer.Write((ushort)value); else { helper.Error("Expected a UInt16 constant"); writer.Write((ushort)0); } break; case ElementType.I4: if (value is int) writer.Write((int)value); else { helper.Error("Expected an Int32 constant"); writer.Write((int)0); } break; case ElementType.U4: if (value is uint) writer.Write((uint)value); else { helper.Error("Expected a UInt32 constant"); writer.Write((uint)0); } break; case ElementType.I8: if (value is long) writer.Write((long)value); else { helper.Error("Expected an Int64 constant"); writer.Write((long)0); } break; case ElementType.U8: if (value is ulong) writer.Write((ulong)value); else { helper.Error("Expected a UInt64 constant"); writer.Write((ulong)0); } break; default: throw new InvalidOperationException(); } } void WriteTypeDefOrRef(BinaryWriter writer, ITypeDefOrRef tdr) { uint codedToken; if (!MD.CodedToken.TypeDefOrRef.Encode(systemMetaData.GetToken(tdr), out codedToken)) { helper.Error("Couldn't encode a TypeDefOrRef"); return; } writer.WriteCompressedUInt32(codedToken); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/PortablePdbCustomDebugInfoReader.cs000066400000000000000000000163761325033663500264710ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info // See Roslyn files: MethodDebugInfo.Portable.cs, MetadataWriter.PortablePdb.cs using System; using System.Diagnostics; using System.IO; using System.Text; using dnlib.DotNet.Emit; using dnlib.DotNet.MD; using dnlib.IO; namespace dnlib.DotNet.Pdb.Portable { struct PortablePdbCustomDebugInfoReader : IDisposable { public static PdbCustomDebugInfo Read(ModuleDef module, TypeDef typeOpt, CilBody bodyOpt, GenericParamContext gpContext, Guid kind, byte[] data) { try { using (var reader = new PortablePdbCustomDebugInfoReader(module, typeOpt, bodyOpt, gpContext, MemoryImageStream.Create(data))) { var cdi = reader.Read(kind); Debug.Assert(reader.reader.Position == reader.reader.Length); return cdi; } } catch (ArgumentException) { } catch (OutOfMemoryException) { } catch (IOException) { } return null; } readonly ModuleDef module; readonly TypeDef typeOpt; readonly CilBody bodyOpt; readonly GenericParamContext gpContext; readonly IBinaryReader reader; PortablePdbCustomDebugInfoReader(ModuleDef module, TypeDef typeOpt, CilBody bodyOpt, GenericParamContext gpContext, IBinaryReader reader) { this.module = module; this.typeOpt = typeOpt; this.bodyOpt = bodyOpt; this.gpContext = gpContext; this.reader = reader; } PdbCustomDebugInfo Read(Guid kind) { if (kind == CustomDebugInfoGuids.AsyncMethodSteppingInformationBlob) return ReadAsyncMethodSteppingInformationBlob(); if (kind == CustomDebugInfoGuids.DefaultNamespace) return ReadDefaultNamespace(); if (kind == CustomDebugInfoGuids.DynamicLocalVariables) return ReadDynamicLocalVariables(reader.Length); if (kind == CustomDebugInfoGuids.EmbeddedSource) return ReadEmbeddedSource(); if (kind == CustomDebugInfoGuids.EncLambdaAndClosureMap) return ReadEncLambdaAndClosureMap(reader.Length); if (kind == CustomDebugInfoGuids.EncLocalSlotMap) return ReadEncLocalSlotMap(reader.Length); if (kind == CustomDebugInfoGuids.SourceLink) return ReadSourceLink(); if (kind == CustomDebugInfoGuids.StateMachineHoistedLocalScopes) return ReadStateMachineHoistedLocalScopes(); if (kind == CustomDebugInfoGuids.TupleElementNames) return ReadTupleElementNames(); Debug.Fail("Unknown custom debug info guid: " + kind.ToString()); return new PdbUnknownCustomDebugInfo(kind, reader.ReadRemainingBytes()); } PdbCustomDebugInfo ReadAsyncMethodSteppingInformationBlob() { if (bodyOpt == null) return null; uint catchHandlerOffset = reader.ReadUInt32() - 1; Instruction catchHandler; if (catchHandlerOffset == uint.MaxValue) catchHandler = null; else { catchHandler = GetInstruction(catchHandlerOffset); Debug.Assert(catchHandler != null); if (catchHandler == null) return null; } var asyncInfo = new PdbAsyncMethodSteppingInformationCustomDebugInfo(); asyncInfo.CatchHandler = catchHandler; while (reader.Position < reader.Length) { var yieldInstr = GetInstruction(reader.ReadUInt32()); Debug.Assert(yieldInstr != null); if (yieldInstr == null) return null; uint resumeOffset = reader.ReadUInt32(); var moveNextRid = reader.ReadCompressedUInt32(); var moveNextToken = new MDToken(Table.Method, moveNextRid); MethodDef moveNextMethod; Instruction resumeInstr; if (gpContext.Method != null && moveNextToken == gpContext.Method.MDToken) { moveNextMethod = gpContext.Method; resumeInstr = GetInstruction(resumeOffset); } else { moveNextMethod = module.ResolveToken(moveNextToken, gpContext) as MethodDef; Debug.Assert(moveNextMethod != null); if (moveNextMethod == null) return null; resumeInstr = GetInstruction(moveNextMethod, resumeOffset); } Debug.Assert(resumeInstr != null); if (resumeInstr == null) return null; asyncInfo.AsyncStepInfos.Add(new PdbAsyncStepInfo(yieldInstr, moveNextMethod, resumeInstr)); } return asyncInfo; } PdbCustomDebugInfo ReadDefaultNamespace() { var defaultNs = Encoding.UTF8.GetString(reader.ReadRemainingBytes()); return new PdbDefaultNamespaceCustomDebugInfo(defaultNs); } PdbCustomDebugInfo ReadDynamicLocalVariables(long recPosEnd) { var flags = new bool[(int)reader.Length * 8]; int w = 0; while (reader.Position < reader.Length) { int b = reader.ReadByte(); for (int i = 1; i < 0x100; i <<= 1) flags[w++] = (b & i) != 0; } return new PdbDynamicLocalVariablesCustomDebugInfo(flags); } PdbCustomDebugInfo ReadEmbeddedSource() { return new PdbEmbeddedSourceCustomDebugInfo(reader.ReadRemainingBytes()); } PdbCustomDebugInfo ReadEncLambdaAndClosureMap(long recPosEnd) { var data = reader.ReadBytes((int)(recPosEnd - reader.Position)); return new PdbEditAndContinueLambdaMapCustomDebugInfo(data); } PdbCustomDebugInfo ReadEncLocalSlotMap(long recPosEnd) { var data = reader.ReadBytes((int)(recPosEnd - reader.Position)); return new PdbEditAndContinueLocalSlotMapCustomDebugInfo(data); } PdbCustomDebugInfo ReadSourceLink() { return new PdbSourceLinkCustomDebugInfo(reader.ReadRemainingBytes()); } PdbCustomDebugInfo ReadStateMachineHoistedLocalScopes() { if (bodyOpt == null) return null; int count = (int)(reader.Length / 8); var smScope = new PdbStateMachineHoistedLocalScopesCustomDebugInfo(count); for (int i = 0; i < count; i++) { uint startOffset = reader.ReadUInt32(); uint length = reader.ReadUInt32(); if (startOffset == 0 && length == 0) smScope.Scopes.Add(new StateMachineHoistedLocalScope()); else { var start = GetInstruction(startOffset); var end = GetInstruction(startOffset + length); Debug.Assert(start != null); if (start == null) return null; smScope.Scopes.Add(new StateMachineHoistedLocalScope(start, end)); } } return smScope; } PdbCustomDebugInfo ReadTupleElementNames() { var tupleListRec = new PortablePdbTupleElementNamesCustomDebugInfo(); while (reader.Position < reader.Length) { var name = ReadUTF8Z(reader.Length); tupleListRec.Names.Add(name); } return tupleListRec; } string ReadUTF8Z(long recPosEnd) { if (reader.Position > recPosEnd) return null; var bytes = reader.ReadBytesUntilByte(0); if (bytes == null) return null; var s = Encoding.UTF8.GetString(bytes); reader.Position++; return s; } Instruction GetInstruction(uint offset) { var instructions = bodyOpt.Instructions; int lo = 0, hi = instructions.Count - 1; while (lo <= hi && hi != -1) { int i = (lo + hi) / 2; var instr = instructions[i]; if (instr.Offset == offset) return instr; if (offset < instr.Offset) hi = i - 1; else lo = i + 1; } return null; } static Instruction GetInstruction(MethodDef method, uint offset) { if (method == null) return null; var body = method.Body; if (body == null) return null; var instructions = body.Instructions; int lo = 0, hi = instructions.Count - 1; while (lo <= hi && hi != -1) { int i = (lo + hi) / 2; var instr = instructions[i]; if (instr.Offset == offset) return instr; if (offset < instr.Offset) hi = i - 1; else lo = i + 1; } return null; } public void Dispose() { reader.Dispose(); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/PortablePdbCustomDebugInfoWriter.cs000066400000000000000000000173661325033663500265430ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using System.Text; using dnlib.DotNet.Emit; using dnlib.DotNet.Writer; namespace dnlib.DotNet.Pdb.Portable { interface IPortablePdbCustomDebugInfoWriterHelper : IWriterError { } struct PortablePdbCustomDebugInfoWriter { readonly IPortablePdbCustomDebugInfoWriterHelper helper; readonly SerializerMethodContext methodContext; readonly MetaData systemMetaData; readonly MemoryStream outStream; readonly BinaryWriter writer; public static byte[] Write(IPortablePdbCustomDebugInfoWriterHelper helper, SerializerMethodContext methodContext, MetaData systemMetaData, PdbCustomDebugInfo cdi, BinaryWriterContext context) { var writer = new PortablePdbCustomDebugInfoWriter(helper, methodContext, systemMetaData, context); return writer.Write(cdi); } PortablePdbCustomDebugInfoWriter(IPortablePdbCustomDebugInfoWriterHelper helper, SerializerMethodContext methodContext, MetaData systemMetaData, BinaryWriterContext context) { this.helper = helper; this.methodContext = methodContext; this.systemMetaData = systemMetaData; this.outStream = context.OutStream; this.writer = context.Writer; outStream.SetLength(0); outStream.Position = 0; } byte[] Write(PdbCustomDebugInfo cdi) { switch (cdi.Kind) { case PdbCustomDebugInfoKind.UsingGroups: case PdbCustomDebugInfoKind.ForwardMethodInfo: case PdbCustomDebugInfoKind.ForwardModuleInfo: case PdbCustomDebugInfoKind.StateMachineTypeName: case PdbCustomDebugInfoKind.DynamicLocals: case PdbCustomDebugInfoKind.TupleElementNames: case PdbCustomDebugInfoKind.IteratorMethod: default: helper.Error("Unreachable code, caller should filter these out"); return null; case PdbCustomDebugInfoKind.StateMachineHoistedLocalScopes: WriteStateMachineHoistedLocalScopes((PdbStateMachineHoistedLocalScopesCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.EditAndContinueLocalSlotMap: WriteEditAndContinueLocalSlotMap((PdbEditAndContinueLocalSlotMapCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.EditAndContinueLambdaMap: WriteEditAndContinueLambdaMap((PdbEditAndContinueLambdaMapCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.Unknown: WriteUnknown((PdbUnknownCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.TupleElementNames_PortablePdb: WriteTupleElementNames((PortablePdbTupleElementNamesCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.DefaultNamespace: WriteDefaultNamespace((PdbDefaultNamespaceCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.DynamicLocalVariables: WriteDynamicLocalVariables((PdbDynamicLocalVariablesCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.EmbeddedSource: WriteEmbeddedSource((PdbEmbeddedSourceCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.SourceLink: WriteSourceLink((PdbSourceLinkCustomDebugInfo)cdi); break; case PdbCustomDebugInfoKind.AsyncMethod: WriteAsyncMethodSteppingInformation((PdbAsyncMethodCustomDebugInfo)cdi); break; } return outStream.ToArray(); } void WriteUTF8Z(string s) { var bytes = Encoding.UTF8.GetBytes(s); writer.Write(bytes); writer.Write((byte)0); } void WriteStateMachineHoistedLocalScopes(PdbStateMachineHoistedLocalScopesCustomDebugInfo cdi) { if (!methodContext.HasBody) { helper.Error("Method has no body, can't write custom debug info: " + cdi.Kind); return; } foreach (var scope in cdi.Scopes) { uint startOffset, endOffset; if (scope.IsSynthesizedLocal) { startOffset = 0; endOffset = 0; } else { var startInstr = scope.Start; if (startInstr == null) { helper.Error("Instruction is null"); return; } startOffset = methodContext.GetOffset(startInstr); endOffset = methodContext.GetOffset(scope.End); } if (startOffset > endOffset) { helper.Error("End instruction is before start instruction"); return; } writer.Write(startOffset); writer.Write(endOffset - startOffset); } } void WriteEditAndContinueLocalSlotMap(PdbEditAndContinueLocalSlotMapCustomDebugInfo cdi) { var d = cdi.Data; if (d == null) { helper.Error("Data blob is null"); return; } writer.Write(d); } void WriteEditAndContinueLambdaMap(PdbEditAndContinueLambdaMapCustomDebugInfo cdi) { var d = cdi.Data; if (d == null) { helper.Error("Data blob is null"); return; } writer.Write(d); } void WriteUnknown(PdbUnknownCustomDebugInfo cdi) { var d = cdi.Data; if (d == null) { helper.Error("Data blob is null"); return; } writer.Write(d); } void WriteTupleElementNames(PortablePdbTupleElementNamesCustomDebugInfo cdi) { foreach (var name in cdi.Names) { if (name == null) { helper.Error("Tuple name is null"); return; } WriteUTF8Z(name); } } void WriteDefaultNamespace(PdbDefaultNamespaceCustomDebugInfo cdi) { var ns = cdi.Namespace; if (ns == null) { helper.Error("Default namespace is null"); return; } var bytes = Encoding.UTF8.GetBytes(ns); writer.Write(bytes); } void WriteDynamicLocalVariables(PdbDynamicLocalVariablesCustomDebugInfo cdi) { var flags = cdi.Flags; for (int i = 0; i < flags.Length; i += 8) writer.Write(ToByte(flags, i)); } static byte ToByte(bool[] flags, int index) { int res = 0; int bit = 1; for (int i = index; i < flags.Length; i++, bit <<= 1) { if (flags[i]) res |= bit; } return (byte)res; } void WriteEmbeddedSource(PdbEmbeddedSourceCustomDebugInfo cdi) { var d = cdi.SourceCodeBlob; if (d == null) { helper.Error("Source code blob is null"); return; } writer.Write(d); } void WriteSourceLink(PdbSourceLinkCustomDebugInfo cdi) { var d = cdi.SourceLinkBlob; if (d == null) { helper.Error("Source link blob is null"); return; } writer.Write(d); } void WriteAsyncMethodSteppingInformation(PdbAsyncMethodCustomDebugInfo cdi) { if (!methodContext.HasBody) { helper.Error("Method has no body, can't write custom debug info: " + cdi.Kind); return; } uint catchHandlerOffset; if (cdi.CatchHandlerInstruction == null) catchHandlerOffset = 0; else catchHandlerOffset = methodContext.GetOffset(cdi.CatchHandlerInstruction) + 1; writer.Write(catchHandlerOffset); foreach (var info in cdi.StepInfos) { if (info.YieldInstruction == null) { helper.Error("YieldInstruction is null"); return; } if (info.BreakpointMethod == null) { helper.Error("BreakpointMethod is null"); return; } if (info.BreakpointInstruction == null) { helper.Error("BreakpointInstruction is null"); return; } uint yieldOffset = methodContext.GetOffset(info.YieldInstruction); uint resumeOffset; if (methodContext.IsSameMethod(info.BreakpointMethod)) resumeOffset = methodContext.GetOffset(info.BreakpointInstruction); else resumeOffset = GetOffsetSlow(info.BreakpointMethod, info.BreakpointInstruction); uint resumeMethodRid = systemMetaData.GetRid(info.BreakpointMethod); writer.Write(yieldOffset); writer.Write(resumeOffset); writer.WriteCompressedUInt32(resumeMethodRid); } } uint GetOffsetSlow(MethodDef method, Instruction instr) { var body = method.Body; if (body == null) { helper.Error("Method has no body"); return uint.MaxValue; } var instrs = body.Instructions; uint offset = 0; for (int i = 0; i < instrs.Count; i++) { var instr2 = instrs[i]; if (instr2 == instr) return offset; offset += (uint)instr2.GetSize(); } helper.Error("Couldn't find an instruction, maybe it was removed. It's still being referenced by some code or by the PDB"); return uint.MaxValue; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/PortablePdbReader.cs000066400000000000000000000406451325033663500235070ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info // https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PortablePdb-Metadata.md using System; using System.Collections.Generic; using System.Diagnostics; using dnlib.DotNet.Emit; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb.Symbols; using dnlib.IO; namespace dnlib.DotNet.Pdb.Portable { sealed class PortablePdbReader : SymbolReader { readonly PdbFileKind pdbFileKind; ModuleDef module; readonly IMetaData pdbMetaData; SymbolDocument[] documents; public override PdbFileKind PdbFileKind { get { return pdbFileKind; } } public override int UserEntryPoint { get { return pdbMetaData.PdbStream.EntryPoint.ToInt32(); } } public override IList Documents { get { return documents; } } public PortablePdbReader(IImageStream pdbStream, PdbFileKind pdbFileKind) { this.pdbFileKind = pdbFileKind; pdbMetaData = MetaDataCreator.CreateStandalonePortablePDB(pdbStream, true); } public override void Initialize(ModuleDef module) { this.module = module; documents = ReadDocuments(); } static Guid GetLanguageVendor(Guid language) { if (language == PdbDocumentConstants.LanguageCSharp || language == PdbDocumentConstants.LanguageVisualBasic || language == PdbDocumentConstants.LanguageFSharp) return PdbDocumentConstants.LanguageVendorMicrosoft; return Guid.Empty; } SymbolDocument[] ReadDocuments() { Debug.Assert(module != null); var docTbl = pdbMetaData.TablesStream.DocumentTable; var docs = new SymbolDocument[docTbl.Rows]; var nameReader = new DocumentNameReader(pdbMetaData.BlobStream); var custInfos = ListCache.AllocList(); var gpContext = new GenericParamContext(); for (int i = 0; i < docs.Length; i++) { uint nameOffset, hashAlgorithmIndex, hashOffset; uint languageIndex = pdbMetaData.TablesStream.ReadDocumentRow2((uint)i + 1, out nameOffset, out hashAlgorithmIndex, out hashOffset); var url = nameReader.ReadDocumentName(nameOffset); var language = pdbMetaData.GuidStream.Read(languageIndex) ?? Guid.Empty; var languageVendor = GetLanguageVendor(language); var documentType = PdbDocumentConstants.DocumentTypeText; var checkSumAlgorithmId = pdbMetaData.GuidStream.Read(hashAlgorithmIndex) ?? Guid.Empty; var checkSum = pdbMetaData.BlobStream.ReadNoNull(hashOffset); var token = new MDToken(Table.Document, i + 1).ToInt32(); custInfos.Clear(); GetCustomDebugInfos(token, gpContext, custInfos); var custInfosArray = custInfos.Count == 0 ? emptyPdbCustomDebugInfos : custInfos.ToArray(); docs[i] = new SymbolDocumentImpl(url, language, languageVendor, documentType, checkSumAlgorithmId, checkSum, custInfosArray); } ListCache.Free(ref custInfos); return docs; } static readonly PdbCustomDebugInfo[] emptyPdbCustomDebugInfos = new PdbCustomDebugInfo[0]; bool TryGetSymbolDocument(uint rid, out SymbolDocument document) { int index = (int)rid - 1; if ((uint)index >= (uint)documents.Length) { Debug.Fail("Couldn't find document with rid 0x" + rid.ToString("X6")); document = null; return false; } document = documents[index]; return true; } public override SymbolMethod GetMethod(MethodDef method, int version) { var mdTable = pdbMetaData.TablesStream.MethodDebugInformationTable; uint methodRid = method.Rid; if (!mdTable.IsValidRID(methodRid)) return null; var sequencePoints = ReadSequencePoints(methodRid) ?? emptySymbolSequencePoints; var gpContext = GenericParamContext.Create(method); var rootScope = ReadScope(methodRid, gpContext); var kickoffMethod = GetKickoffMethod(methodRid); var symbolMethod = new SymbolMethodImpl(this, method.MDToken.ToInt32(), rootScope, sequencePoints, kickoffMethod); rootScope.method = symbolMethod; return symbolMethod; } static readonly SymbolAsyncStepInfo[] emptySymbolAsyncStepInfos = new SymbolAsyncStepInfo[0]; int GetKickoffMethod(uint methodRid) { uint rid = pdbMetaData.GetStateMachineMethodRid(methodRid); if (rid == 0) return 0; if (!pdbMetaData.TablesStream.StateMachineMethodTable.IsValidRID(rid)) return 0; return 0x06000000 + (int)pdbMetaData.TablesStream.ReadStateMachineMethodRow2(rid); } SymbolSequencePoint[] ReadSequencePoints(uint methodRid) { if (!pdbMetaData.TablesStream.MethodDebugInformationTable.IsValidRID(methodRid)) return null; uint documentRid; uint sequencePointsOffset = pdbMetaData.TablesStream.ReadMethodDebugInformationRow2(methodRid, out documentRid); if (sequencePointsOffset == 0) return null; var seqPointsBuilder = ListCache.AllocList(); using (var seqPointsStream = pdbMetaData.BlobStream.CreateStream(sequencePointsOffset)) { uint localSig = seqPointsStream.ReadCompressedUInt32(); if (documentRid == 0) documentRid = seqPointsStream.ReadCompressedUInt32(); SymbolDocument document; TryGetSymbolDocument(documentRid, out document); uint ilOffset = uint.MaxValue; int line = -1, column = 0; bool canReadDocumentRecord = false; while (seqPointsStream.Position < seqPointsStream.Length) { uint data = seqPointsStream.ReadCompressedUInt32(); if (data == 0 && canReadDocumentRecord) { // document-record documentRid = seqPointsStream.ReadCompressedUInt32(); TryGetSymbolDocument(documentRid, out document); } else { // SequencePointRecord Debug.Assert(document != null); if (document == null) return null; var symSeqPoint = new SymbolSequencePoint { Document = document, }; if (ilOffset == uint.MaxValue) ilOffset = data; else { Debug.Assert(data != 0); if (data == 0) return null; ilOffset += data; } symSeqPoint.Offset = (int)ilOffset; uint dlines = seqPointsStream.ReadCompressedUInt32(); int dcolumns = dlines == 0 ? (int)seqPointsStream.ReadCompressedUInt32() : seqPointsStream.ReadCompressedInt32(); if (dlines == 0 && dcolumns == 0) { // hidden-sequence-point-record symSeqPoint.Line = SequencePointConstants.HIDDEN_LINE; symSeqPoint.EndLine = SequencePointConstants.HIDDEN_LINE; symSeqPoint.Column = SequencePointConstants.HIDDEN_COLUMN; symSeqPoint.EndColumn = SequencePointConstants.HIDDEN_COLUMN; } else { // sequence-point-record if (line < 0) { line = (int)seqPointsStream.ReadCompressedUInt32(); column = (int)seqPointsStream.ReadCompressedUInt32(); } else { line += seqPointsStream.ReadCompressedInt32(); column += seqPointsStream.ReadCompressedInt32(); } symSeqPoint.Line = line; symSeqPoint.EndLine = line + (int)dlines; symSeqPoint.Column = column; symSeqPoint.EndColumn = column + dcolumns; } seqPointsBuilder.Add(symSeqPoint); } canReadDocumentRecord = true; } Debug.Assert(seqPointsStream.Position == seqPointsStream.Length); } return ListCache.FreeAndToArray(ref seqPointsBuilder); } static readonly SymbolSequencePoint[] emptySymbolSequencePoints = new SymbolSequencePoint[0]; SymbolScopeImpl ReadScope(uint methodRid, GenericParamContext gpContext) { var scopesRidList = pdbMetaData.GetLocalScopeRidList(methodRid); SymbolScopeImpl rootScopeOrNull = null; if (scopesRidList.Count != 0) { var custInfos = ListCache.AllocList(); var stack = ListCache.AllocList(); var importScopeBlobReader = new ImportScopeBlobReader(module, pdbMetaData.BlobStream); for (int i = 0; i < scopesRidList.Count; i++) { var rid = scopesRidList[i]; uint importScope, variableList, constantList, startOffset; int token = new MDToken(Table.LocalScope, rid).ToInt32(); uint length = pdbMetaData.TablesStream.ReadLocalScopeRow2(rid, out importScope, out variableList, out constantList, out startOffset); uint endOffset = startOffset + length; SymbolScopeImpl parent = null; while (stack.Count > 0) { var nextParent = stack[stack.Count - 1]; if (startOffset >= nextParent.StartOffset && endOffset <= nextParent.EndOffset) { parent = nextParent; break; } stack.RemoveAt(stack.Count - 1); } Debug.Assert(parent != null || rootScopeOrNull == null); custInfos.Clear(); GetCustomDebugInfos(token, gpContext, custInfos); var customDebugInfos = custInfos.Count == 0 ? emptyPdbCustomDebugInfos : custInfos.ToArray(); var scope = new SymbolScopeImpl(this, parent, (int)startOffset, (int)endOffset, customDebugInfos); if (rootScopeOrNull == null) rootScopeOrNull = scope; stack.Add(scope); if (parent != null) parent.childrenList.Add(scope); scope.importScope = ReadPdbImportScope(ref importScopeBlobReader, importScope, gpContext); uint variableListEnd, constantListEnd; GetEndOfLists(rid, out variableListEnd, out constantListEnd); ReadVariables(scope, gpContext, variableList, variableListEnd); ReadConstants(scope, constantList, constantListEnd); } ListCache.Free(ref stack); ListCache.Free(ref custInfos); } return rootScopeOrNull ?? new SymbolScopeImpl(this, null, 0, int.MaxValue, emptyPdbCustomDebugInfos); } void GetEndOfLists(uint scopeRid, out uint variableListEnd, out uint constantListEnd) { var localScopeTable = pdbMetaData.TablesStream.LocalScopeTable; var nextRid = scopeRid + 1; if (!localScopeTable.IsValidRID(nextRid)) { variableListEnd = pdbMetaData.TablesStream.LocalVariableTable.Rows + 1; constantListEnd = pdbMetaData.TablesStream.LocalConstantTable.Rows + 1; } else { uint nextImportScope, nextVariableList, nextConstantList, nextStartOffset; pdbMetaData.TablesStream.ReadLocalScopeRow2(nextRid, out nextImportScope, out nextVariableList, out nextConstantList, out nextStartOffset); variableListEnd = nextVariableList; constantListEnd = nextConstantList; } } PdbImportScope ReadPdbImportScope(ref ImportScopeBlobReader importScopeBlobReader, uint importScope, GenericParamContext gpContext) { if (importScope == 0) return null; const int MAX = 1000; PdbImportScope result = null; PdbImportScope prevScope = null; for (int i = 0; importScope != 0; i++) { Debug.Assert(i < MAX); if (i >= MAX) return null; int token = new MDToken(Table.ImportScope, importScope).ToInt32(); if (!pdbMetaData.TablesStream.ImportScopeTable.IsValidRID(importScope)) return null; uint imports = pdbMetaData.TablesStream.ReadImportScopeRow2(importScope, out importScope); var scope = new PdbImportScope(); GetCustomDebugInfos(token, gpContext, scope.CustomDebugInfos); if (result == null) result = scope; if (prevScope != null) prevScope.Parent = scope; importScopeBlobReader.Read(imports, scope.Imports); prevScope = scope; } return result; } void ReadVariables(SymbolScopeImpl scope, GenericParamContext gpContext, uint variableList, uint variableListEnd) { if (variableList == 0) return; Debug.Assert(variableList <= variableListEnd); if (variableList >= variableListEnd) return; var table = pdbMetaData.TablesStream.LocalVariableTable; Debug.Assert(table.IsValidRID(variableListEnd - 1)); if (!table.IsValidRID(variableListEnd - 1)) return; Debug.Assert(table.IsValidRID(variableList)); if (!table.IsValidRID(variableList)) return; var custInfos = ListCache.AllocList(); for (uint rid = variableList; rid < variableListEnd; rid++) { int token = new MDToken(Table.LocalVariable, rid).ToInt32(); custInfos.Clear(); GetCustomDebugInfos(token, gpContext, custInfos); var customDebugInfos = custInfos.Count == 0 ? emptyPdbCustomDebugInfos : custInfos.ToArray(); ushort attributes, index; var nameOffset = pdbMetaData.TablesStream.ReadLocalVariableRow2(rid, out attributes, out index); var name = pdbMetaData.StringsStream.Read(nameOffset); scope.localsList.Add(new SymbolVariableImpl(name, ToSymbolVariableAttributes(attributes), index, customDebugInfos)); } ListCache.Free(ref custInfos); } static PdbLocalAttributes ToSymbolVariableAttributes(ushort attributes) { var res = PdbLocalAttributes.None; const ushort DebuggerHidden = 0x0001; if ((attributes & DebuggerHidden) != 0) res |= PdbLocalAttributes.DebuggerHidden; return res; } void ReadConstants(SymbolScopeImpl scope, uint constantList, uint constantListEnd) { if (constantList == 0) return; Debug.Assert(constantList <= constantListEnd); if (constantList >= constantListEnd) return; var table = pdbMetaData.TablesStream.LocalConstantTable; Debug.Assert(table.IsValidRID(constantListEnd - 1)); if (!table.IsValidRID(constantListEnd - 1)) return; Debug.Assert(table.IsValidRID(constantList)); if (!table.IsValidRID(constantList)) return; scope.SetConstants(pdbMetaData, constantList, constantListEnd); } internal void GetCustomDebugInfos(SymbolMethodImpl symMethod, MethodDef method, CilBody body, IList result) { Debug.Assert(method.Module == module); PdbAsyncMethodSteppingInformationCustomDebugInfo asyncStepInfo; GetCustomDebugInfos(method.MDToken.ToInt32(), GenericParamContext.Create(method), result, method, body, out asyncStepInfo); if (asyncStepInfo != null) { var asyncMethod = TryCreateAsyncMethod(module, symMethod.KickoffMethod, asyncStepInfo.AsyncStepInfos, asyncStepInfo.CatchHandler); Debug.Assert(asyncMethod != null); if (asyncMethod != null) result.Add(asyncMethod); } else if (symMethod.KickoffMethod != 0) { var iteratorMethod = TryCreateIteratorMethod(module, symMethod.KickoffMethod); Debug.Assert(iteratorMethod != null); if (iteratorMethod != null) result.Add(iteratorMethod); } } PdbAsyncMethodCustomDebugInfo TryCreateAsyncMethod(ModuleDef module, int asyncKickoffMethod, IList asyncStepInfos, Instruction asyncCatchHandler) { var kickoffToken = new MDToken(asyncKickoffMethod); if (kickoffToken.Table != Table.Method) return null; var asyncMethod = new PdbAsyncMethodCustomDebugInfo(asyncStepInfos.Count); asyncMethod.KickoffMethod = module.ResolveToken(kickoffToken) as MethodDef; asyncMethod.CatchHandlerInstruction = asyncCatchHandler; foreach (var info in asyncStepInfos) asyncMethod.StepInfos.Add(info); return asyncMethod; } PdbIteratorMethodCustomDebugInfo TryCreateIteratorMethod(ModuleDef module, int iteratorKickoffMethod) { var kickoffToken = new MDToken(iteratorKickoffMethod); if (kickoffToken.Table != Table.Method) return null; var kickoffMethod = module.ResolveToken(kickoffToken) as MethodDef; return new PdbIteratorMethodCustomDebugInfo(kickoffMethod); } public override void GetCustomDebugInfos(int token, GenericParamContext gpContext, IList result) { PdbAsyncMethodSteppingInformationCustomDebugInfo asyncStepInfo; GetCustomDebugInfos(token, gpContext, result, null, null, out asyncStepInfo); Debug.Assert(asyncStepInfo == null); } void GetCustomDebugInfos(int token, GenericParamContext gpContext, IList result, MethodDef methodOpt, CilBody bodyOpt, out PdbAsyncMethodSteppingInformationCustomDebugInfo asyncStepInfo) { asyncStepInfo = null; var mdToken = new MDToken(token); var ridList = pdbMetaData.GetCustomDebugInformationRidList(mdToken.Table, mdToken.Rid); if (ridList.Count == 0) return; var typeOpt = methodOpt == null ? null : methodOpt.DeclaringType; for (int i = 0; i < ridList.Count; i++) { var rid = ridList[i]; uint kind; uint value = pdbMetaData.TablesStream.ReadCustomDebugInformationRow2(rid, out kind); var guid = pdbMetaData.GuidStream.Read(kind); var data = pdbMetaData.BlobStream.Read(value); Debug.Assert(guid != null && data != null); if (guid == null || data == null) continue; var cdi = PortablePdbCustomDebugInfoReader.Read(module, typeOpt, bodyOpt, gpContext, guid.Value, data); Debug.Assert(cdi != null); if (cdi != null) { var asyncStepInfoTmp = cdi as PdbAsyncMethodSteppingInformationCustomDebugInfo; if (asyncStepInfoTmp != null) { Debug.Assert(asyncStepInfo == null); asyncStepInfo = asyncStepInfoTmp; } else result.Add(cdi); } } } public override void Dispose() { pdbMetaData.Dispose(); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/SequencePointConstants.cs000066400000000000000000000003171325033663500246350ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Pdb.Portable { static class SequencePointConstants { public const int HIDDEN_LINE = 0xFEEFEE; public const int HIDDEN_COLUMN = 0; } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/SymbolDocumentImpl.cs000066400000000000000000000041711325033663500237460ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.Text; using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet.Pdb.Portable { [DebuggerDisplay("{GetDebuggerString(),nq}")] sealed class SymbolDocumentImpl : SymbolDocument { readonly string url; /*readonly*/ Guid language; /*readonly*/ Guid languageVendor; /*readonly*/ Guid documentType; /*readonly*/ Guid checkSumAlgorithmId; readonly byte[] checkSum; readonly PdbCustomDebugInfo[] customDebugInfos; string GetDebuggerString() { var sb = new StringBuilder(); if (language == PdbDocumentConstants.LanguageCSharp) sb.Append("C#"); else if (language == PdbDocumentConstants.LanguageVisualBasic) sb.Append("VB"); else if (language == PdbDocumentConstants.LanguageFSharp) sb.Append("F#"); else sb.Append(language.ToString()); sb.Append(", "); if (checkSumAlgorithmId == PdbDocumentConstants.HashSHA1) sb.Append("SHA-1"); else if (checkSumAlgorithmId == PdbDocumentConstants.HashSHA256) sb.Append("SHA-256"); else sb.Append(checkSumAlgorithmId.ToString()); sb.Append(": "); sb.Append(url); return sb.ToString(); } public override string URL { get { return url; } } public override Guid Language { get { return language; } } public override Guid LanguageVendor { get { return languageVendor; } } public override Guid DocumentType { get { return documentType; } } public override Guid CheckSumAlgorithmId { get { return checkSumAlgorithmId; } } public override byte[] CheckSum { get { return checkSum; } } public override PdbCustomDebugInfo[] CustomDebugInfos { get { return customDebugInfos; } } public SymbolDocumentImpl(string url, Guid language, Guid languageVendor, Guid documentType, Guid checkSumAlgorithmId, byte[] checkSum, PdbCustomDebugInfo[] customDebugInfos) { this.url = url; this.language = language; this.languageVendor = languageVendor; this.documentType = documentType; this.checkSumAlgorithmId = checkSumAlgorithmId; this.checkSum = checkSum; this.customDebugInfos = customDebugInfos; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/SymbolMethodImpl.cs000066400000000000000000000022431325033663500234060ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using dnlib.DotNet.Emit; using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet.Pdb.Portable { sealed class SymbolMethodImpl : SymbolMethod { readonly PortablePdbReader reader; readonly int token; readonly SymbolScope rootScope; readonly SymbolSequencePoint[] sequencePoints; readonly int kickoffMethod; public override int Token { get { return token; } } public override SymbolScope RootScope { get { return rootScope; } } public override IList SequencePoints { get { return sequencePoints; } } public int KickoffMethod { get { return kickoffMethod; } } public SymbolMethodImpl(PortablePdbReader reader, int token, SymbolScope rootScope, SymbolSequencePoint[] sequencePoints, int kickoffMethod) { this.reader = reader; this.token = token; this.rootScope = rootScope; this.sequencePoints = sequencePoints; this.kickoffMethod = kickoffMethod; } public override void GetCustomDebugInfos(MethodDef method, CilBody body, IList result) { reader.GetCustomDebugInfos(this, method, body, result); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/SymbolReaderCreator.cs000066400000000000000000000047461325033663500241000ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Diagnostics; using System.IO; using System.IO.Compression; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb.Symbols; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Pdb.Portable { static class SymbolReaderCreator { public static SymbolReader TryCreate(IImageStream pdbStream, bool isEmbeddedPortablePdb) { try { if (pdbStream != null) { pdbStream.Position = 0; if (pdbStream.ReadUInt32() == 0x424A5342) { pdbStream.Position = 0; return new PortablePdbReader(pdbStream, isEmbeddedPortablePdb ? PdbFileKind.EmbeddedPortablePDB : PdbFileKind.PortablePDB); } } } catch (IOException) { } if (pdbStream != null) pdbStream.Dispose(); return null; } public static SymbolReader TryCreate(IMetaData metaData) { if (metaData == null) return null; try { var peImage = metaData.PEImage; if (peImage == null) return null; var embeddedDir = TryGetEmbeddedDebugDirectory(peImage); if (embeddedDir == null) return null; using (var reader = peImage.CreateStream(embeddedDir.PointerToRawData, embeddedDir.SizeOfData)) { // "MPDB" = 0x4244504D if (reader.ReadUInt32() != 0x4244504D) return null; uint uncompressedSize = reader.ReadUInt32(); // If this fails, see the (hopefully) updated spec: // https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PE-COFF.md#embedded-portable-pdb-debug-directory-entry-type-17 bool newVersion = (uncompressedSize & 0x80000000) != 0; Debug.Assert(!newVersion); if (newVersion) return null; var decompressedBytes = new byte[uncompressedSize]; using (var deflateStream = new DeflateStream(new MemoryStream(reader.ReadRemainingBytes()), CompressionMode.Decompress)) { int pos = 0; while (pos < decompressedBytes.Length) { int read = deflateStream.Read(decompressedBytes, pos, decompressedBytes.Length - pos); if (read == 0) break; pos += read; } if (pos != decompressedBytes.Length) return null; var stream = MemoryImageStream.Create(decompressedBytes); return TryCreate(stream, true); } } } catch (IOException) { } return null; } static ImageDebugDirectory TryGetEmbeddedDebugDirectory(IPEImage peImage) { foreach (var idd in peImage.ImageDebugDirectories) { if (idd.Type == ImageDebugType.EmbeddedPortablePdb) return idd; } return null; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/SymbolScopeImpl.cs000066400000000000000000000071111325033663500232360ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet.Pdb.Portable { sealed class SymbolScopeImpl : SymbolScope { readonly PortablePdbReader owner; internal SymbolMethod method; readonly SymbolScopeImpl parent; readonly int startOffset; readonly int endOffset; internal readonly List childrenList; internal readonly List localsList; internal PdbImportScope importScope; readonly PdbCustomDebugInfo[] customDebugInfos; public override SymbolMethod Method { get { if (method != null) return method; var p = parent; if (p == null) return method; for (;;) { if (p.parent == null) return method = p.method; p = p.parent; } } } public override SymbolScope Parent { get { return parent; } } public override int StartOffset { get { return startOffset; } } public override int EndOffset { get { return endOffset; } } public override IList Children { get { return childrenList; } } public override IList Locals { get { return localsList; } } public override IList Namespaces { get { return emptySymbolNamespaces; } } static readonly SymbolNamespace[] emptySymbolNamespaces = new SymbolNamespace[0]; public override IList CustomDebugInfos { get { return customDebugInfos; } } public override PdbImportScope ImportScope { get { return importScope; } } public SymbolScopeImpl(PortablePdbReader owner, SymbolScopeImpl parent, int startOffset, int endOffset, PdbCustomDebugInfo[] customDebugInfos) { this.owner = owner; method = null; this.parent = parent; this.startOffset = startOffset; this.endOffset = endOffset; childrenList = new List(); localsList = new List(); this.customDebugInfos = customDebugInfos; } IMetaData constantsMetaData; uint constantList; uint constantListEnd; internal void SetConstants(IMetaData metaData, uint constantList, uint constantListEnd) { constantsMetaData = metaData; this.constantList = constantList; this.constantListEnd = constantListEnd; } public override IList GetConstants(ModuleDef module, GenericParamContext gpContext) { if (constantList >= constantListEnd) return emptyPdbConstants; Debug.Assert(constantsMetaData != null); var res = new PdbConstant[constantListEnd - constantList]; int w = 0; for (int i = 0; i < res.Length; i++) { uint rid = constantList + (uint)i; uint nameOffset; uint signature = constantsMetaData.TablesStream.ReadLocalConstantRow2(rid, out nameOffset); var name = constantsMetaData.StringsStream.Read(nameOffset); using (var stream = constantsMetaData.BlobStream.CreateStream(signature)) { var localConstantSigBlobReader = new LocalConstantSigBlobReader(module, stream, gpContext); TypeSig type; object value; bool b = localConstantSigBlobReader.Read(out type, out value); Debug.Assert(b); if (b) { var pdbConstant = new PdbConstant(name, type, value); int token = new MDToken(Table.LocalConstant, rid).ToInt32(); owner.GetCustomDebugInfos(token, gpContext, pdbConstant.CustomDebugInfos); res[w++] = pdbConstant; } Debug.Assert(stream.Position == stream.Length); } } if (res.Length != w) Array.Resize(ref res, w); return res; } static readonly PdbConstant[] emptyPdbConstants = new PdbConstant[0]; } } dnlib-2.1_VS2010/src/DotNet/Pdb/Portable/SymbolVariableImpl.cs000066400000000000000000000015421325033663500237140ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet.Pdb.Portable { sealed class SymbolVariableImpl : SymbolVariable { readonly string name; readonly PdbLocalAttributes attributes; readonly int index; readonly PdbCustomDebugInfo[] customDebugInfos; public override string Name { get { return name; } } public override PdbLocalAttributes Attributes { get { return attributes; } } public override int Index { get { return index; } } public override PdbCustomDebugInfo[] CustomDebugInfos { get { return customDebugInfos; } } public SymbolVariableImpl(string name, PdbLocalAttributes attributes, int index, PdbCustomDebugInfo[] customDebugInfos) { this.name = name; this.attributes = attributes; this.index = index; this.customDebugInfos = customDebugInfos; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/SequencePoint.cs000066400000000000000000000020361325033663500211700ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Diagnostics; namespace dnlib.DotNet.Pdb { /// /// PDB sequence point /// [DebuggerDisplay("({StartLine}, {StartColumn}) - ({EndLine}, {EndColumn}) {Document.Url}")] public sealed class SequencePoint { /// /// PDB document /// public PdbDocument Document { get; set; } /// /// Start line /// public int StartLine { get; set; } /// /// Start column /// public int StartColumn { get; set; } /// /// End line /// public int EndLine { get; set; } /// /// End column /// public int EndColumn { get; set; } /// /// Clones this instance /// /// A new cloned instance public SequencePoint Clone() { return new SequencePoint() { Document = Document, StartLine = StartLine, StartColumn = StartColumn, EndLine = EndLine, EndColumn = EndColumn, }; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/SymbolReaderCreator.cs000066400000000000000000000075441325033663500223270ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb.Symbols; using dnlib.IO; namespace dnlib.DotNet.Pdb { /// /// Creates a instance /// public static class SymbolReaderCreator { /// /// Creates a new instance /// /// PDB implementation to use /// .NET metadata /// Path to assembly /// A new instance or null if there's no PDB /// file on disk or if it's not possible to create a . public static SymbolReader CreateFromAssemblyFile(PdbImplType pdbImpl, IMetaData metaData, string assemblyFileName) { switch (pdbImpl) { case PdbImplType.MicrosoftCOM: return Dss.SymbolReaderCreator.CreateFromAssemblyFile(assemblyFileName); case PdbImplType.Managed: return ManagedSymbolReaderCreator.CreateFromAssemblyFile(metaData, assemblyFileName); default: throw new InvalidOperationException(); } } /// /// Creates a new instance /// /// PDB implementation to use /// .NET metadata /// Path to PDB file /// A new instance or null if there's no PDB /// file on disk or if it's not possible to create a . public static SymbolReader Create(PdbImplType pdbImpl, IMetaData metaData, string pdbFileName) { switch (pdbImpl) { case PdbImplType.MicrosoftCOM: return Dss.SymbolReaderCreator.Create(metaData, pdbFileName); case PdbImplType.Managed: return ManagedSymbolReaderCreator.Create(metaData, pdbFileName); default: throw new InvalidOperationException(); } } /// /// Creates a new instance /// /// PDB implementation to use /// .NET metadata /// PDB file data /// A new instance or null if it's not possible /// to create a . public static SymbolReader Create(PdbImplType pdbImpl, IMetaData metaData, byte[] pdbData) { switch (pdbImpl) { case PdbImplType.MicrosoftCOM: return Dss.SymbolReaderCreator.Create(metaData, pdbData); case PdbImplType.Managed: return ManagedSymbolReaderCreator.Create(metaData, pdbData); default: throw new InvalidOperationException(); } } /// /// Creates a new instance /// /// PDB implementation to use /// .NET metadata /// PDB file stream which is now owned by us /// A new instance or null if it's not possible /// to create a . public static SymbolReader Create(PdbImplType pdbImpl, IMetaData metaData, IImageStream pdbStream) { switch (pdbImpl) { case PdbImplType.MicrosoftCOM: return Dss.SymbolReaderCreator.Create(metaData, pdbStream); case PdbImplType.Managed: return ManagedSymbolReaderCreator.Create(metaData, pdbStream); default: if (pdbStream != null) pdbStream.Dispose(); throw new InvalidOperationException(); } } internal static SymbolReader Create(PdbImplType pdbImpl, IMetaData metaData) { switch (pdbImpl) { case PdbImplType.MicrosoftCOM: return null; case PdbImplType.Managed: return ManagedSymbolReaderCreator.Create(metaData); default: throw new InvalidOperationException(); } } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Symbols/000077500000000000000000000000001325033663500175065ustar00rootroot00000000000000dnlib-2.1_VS2010/src/DotNet/Pdb/Symbols/SymbolAsyncStepInfo.cs000066400000000000000000000015661325033663500237600ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Pdb.Symbols { /// /// Async step info /// public struct SymbolAsyncStepInfo { /// /// Yield offset /// public uint YieldOffset; /// /// Breakpoint offset /// public uint BreakpointOffset; /// /// Breakpoint method token /// public uint BreakpointMethod; /// /// Constructor /// /// Yield offset /// Breakpoint offset /// Breakpoint method token public SymbolAsyncStepInfo(uint yieldOffset, uint breakpointOffset, uint breakpointMethod) { YieldOffset = yieldOffset; BreakpointOffset = breakpointOffset; BreakpointMethod = breakpointMethod; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Symbols/SymbolDocument.cs000066400000000000000000000016721325033663500230070ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet.Pdb.Symbols { /// /// A document /// public abstract class SymbolDocument { /// /// Gets the URL /// public abstract string URL { get; } /// /// Gets the language /// public abstract Guid Language { get; } /// /// Gets the language vendor /// public abstract Guid LanguageVendor { get; } /// /// Gets the document type /// public abstract Guid DocumentType { get; } /// /// Gets the checksum algorithm id /// public abstract Guid CheckSumAlgorithmId { get; } /// /// Gets the checksum /// public abstract byte[] CheckSum { get; } /// /// Gets the custom debug infos /// public abstract PdbCustomDebugInfo[] CustomDebugInfos { get; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Symbols/SymbolMethod.cs000066400000000000000000000016011325033663500224410ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using dnlib.DotNet.Emit; namespace dnlib.DotNet.Pdb.Symbols { /// /// A method /// public abstract class SymbolMethod { /// /// Gets the method token /// public abstract int Token { get; } /// /// Gets the root scope /// public abstract SymbolScope RootScope { get; } /// /// Gets all sequence points /// public abstract IList SequencePoints { get; } /// /// Reads custom debug info /// /// Method /// Method body /// Updated with custom debug info public abstract void GetCustomDebugInfos(MethodDef method, CilBody body, IList result); } } dnlib-2.1_VS2010/src/DotNet/Pdb/Symbols/SymbolNamespace.cs000066400000000000000000000004131325033663500231150ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Pdb.Symbols { /// /// A namespace /// public abstract class SymbolNamespace { /// /// Gets the name /// public abstract string Name { get; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Symbols/SymbolReader.cs000066400000000000000000000032231325033663500224250ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using dnlib.DotNet.Emit; namespace dnlib.DotNet.Pdb.Symbols { /// /// Reads symbols from a PDB file /// public abstract class SymbolReader : IDisposable { /// /// Called by the owner module before any other methods and properties are called /// /// Owner module public abstract void Initialize(ModuleDef module); /// /// Gets the PDB file kind /// public abstract PdbFileKind PdbFileKind { get; } /// /// Gets the user entry point token or 0 if none /// public abstract int UserEntryPoint { get; } /// /// Gets all documents /// public abstract IList Documents { get; } /// /// Gets a method or returns null if the method doesn't exist in the PDB file /// /// Method /// Edit and continue version /// public abstract SymbolMethod GetMethod(MethodDef method, int version); /// /// Reads custom debug info /// /// Token of a instance /// Generic parameter context /// Updated with custom debug info public abstract void GetCustomDebugInfos(int token, GenericParamContext gpContext, IList result); /// /// Cleans up resources /// public virtual void Dispose() { } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Symbols/SymbolScope.cs000066400000000000000000000032101325033663500222700ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; namespace dnlib.DotNet.Pdb.Symbols { /// /// A scope /// public abstract class SymbolScope { /// /// Gets the method /// public abstract SymbolMethod Method { get; } /// /// Gets the parent scope /// public abstract SymbolScope Parent { get; } /// /// Gets the start offset of the scope in the method /// public abstract int StartOffset { get; } /// /// Gets the end offset of the scope in the method /// public abstract int EndOffset { get; } /// /// Gets all child scopes /// public abstract IList Children { get; } /// /// Gets all locals defined in this scope /// public abstract IList Locals { get; } /// /// Gets all namespaces in this scope /// public abstract IList Namespaces { get; } /// /// Gets all custom debug infos /// public abstract IList CustomDebugInfos { get; } /// /// Gets the import scope or null if none /// public abstract PdbImportScope ImportScope { get; } /// /// Gets all the constants /// /// Owner module if a signature must be read from the #Blob /// Generic parameter context /// public abstract IList GetConstants(ModuleDef module, GenericParamContext gpContext); } } dnlib-2.1_VS2010/src/DotNet/Pdb/Symbols/SymbolSequencePoint.cs000066400000000000000000000021621325033663500240060ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Diagnostics; using System.Text; namespace dnlib.DotNet.Pdb.Symbols { /// /// Sequence point /// [DebuggerDisplay("{GetDebuggerString(),nq}")] public struct SymbolSequencePoint { /// /// IL offset /// public int Offset; /// /// Document /// public SymbolDocument Document; /// /// Start line /// public int Line; /// /// Start column /// public int Column; /// /// End line /// public int EndLine; /// /// End column /// public int EndColumn; string GetDebuggerString() { var sb = new StringBuilder(); if (Line == 0xFEEFEE && EndLine == 0xFEEFEE) sb.Append(""); else { sb.Append("("); sb.Append(Line); sb.Append(","); sb.Append(Column); sb.Append(")-("); sb.Append(EndLine); sb.Append(","); sb.Append(EndColumn); sb.Append(")"); } sb.Append(": "); sb.Append(Document.URL); return sb.ToString(); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/Symbols/SymbolVariable.cs000066400000000000000000000011571325033663500227540ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Pdb.Symbols { /// /// A variable /// public abstract class SymbolVariable { /// /// Gets the name /// public abstract string Name { get; } /// /// Gets the attributes /// public abstract PdbLocalAttributes Attributes { get; } /// /// Gets the index of the variable /// public abstract int Index { get; } /// /// Gets all custom debug infos /// public abstract PdbCustomDebugInfo[] CustomDebugInfos { get; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/WindowsPdb/000077500000000000000000000000001325033663500201365ustar00rootroot00000000000000dnlib-2.1_VS2010/src/DotNet/Pdb/WindowsPdb/CorSymVarFlag.cs000066400000000000000000000002601325033663500231420ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet.Pdb.WindowsPdb { [Flags] enum CorSymVarFlag : uint { VAR_IS_COMP_GEN = 0x00000001, } } dnlib-2.1_VS2010/src/DotNet/Pdb/WindowsPdb/CustomDebugInfoConstants.cs000066400000000000000000000003101325033663500254110ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Pdb.WindowsPdb { static class CustomDebugInfoConstants { public const int Version = 4; public const int RecordVersion = 4; } } dnlib-2.1_VS2010/src/DotNet/Pdb/WindowsPdb/ISymbolWriter2.cs000066400000000000000000000075511325033663500233320ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics.SymbolStore; using dnlib.DotNet.Writer; namespace dnlib.DotNet.Pdb.WindowsPdb { /// /// Implements and adds a few extra methods we need that are part of /// ISymUnmanagedWriter and ISymUnmanagedWriter2 but not present in /// . /// public interface ISymbolWriter2 : ISymbolWriter, IDisposable { /// /// Same as except that this method has an /// extra that specifies the size of all the arrays. /// /// Document /// Size of the arrays /// Offsets /// Start lines /// Start columns /// End lines /// End columns void DefineSequencePoints(ISymbolDocumentWriter document, uint arraySize, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns); /// /// Gets debug info. See ISymUnmanagedWriter.GetDebugInfo() /// /// Updated by writer /// Debug data for the symbol store byte[] GetDebugInfo(out IMAGE_DEBUG_DIRECTORY pIDD); /// /// Define a local. See ISymUnmanagedWriter2.DefineLocalVariable2() /// /// Name /// Attributes /// Signature token /// Address kind /// Address #1 /// Address #2 /// Address #3 /// Start offset /// End offset void DefineLocalVariable2(string name, uint attributes, uint sigToken, uint addrKind, uint addr1, uint addr2, uint addr3, uint startOffset, uint endOffset); /// /// Initializes this instance. This must be called before any other method. /// /// Metadata void Initialize(MetaData metaData); } /// /// Implements and adds a few extra methods we need that are part of /// ISymUnmanagedWriter and ISymUnmanagedWriter2 but not present in /// . /// public interface ISymbolWriter3 : ISymbolWriter2 { /// /// Defines a constant /// /// Name of constant /// Constant value /// StandAloneSig token of constant field type void DefineConstant2(string name, object value, uint sigToken); /// /// true if it supports , /// and /// bool SupportsAsyncMethods { get; } /// /// Defines an async kickoff method /// /// Kickoff method token void DefineKickoffMethod(uint kickoffMethod); /// /// Defines an async catch handler /// /// Catch handler IL offset void DefineCatchHandlerILOffset(uint catchHandlerOffset); /// /// Defines async step info /// /// Yield IL offsets /// Breakpoint method IL offset /// Breakpoint method void DefineAsyncStepInfo(uint[] yieldOffsets, uint[] breakpointOffset, uint[] breakpointMethod); } } dnlib-2.1_VS2010/src/DotNet/Pdb/WindowsPdb/PdbCustomDebugInfoReader.cs000066400000000000000000000252721325033663500253030ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info // C# & Visual Basic compiler's Custom Debug Info is "documented" in source code only, see Roslyn classes: // CustomDebugInfoReader, CustomDebugInfoWriter, CustomDebugInfoEncoder using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; using dnlib.DotNet.Emit; using dnlib.IO; using dnlib.Threading; namespace dnlib.DotNet.Pdb.WindowsPdb { /// /// Reads custom debug infos produced by the C# and Visual Basic compilers. They're stored in PDB files /// as PDB method custom attributes with the name "MD2". /// struct PdbCustomDebugInfoReader : IDisposable { /// /// Reads custom debug info /// /// Method /// The method's body. Needs to be provided by the caller since we're called from /// PDB-init code when the Body property hasn't been initialized yet /// Place all custom debug info in this list /// Custom debug info from the PDB file public static void Read(MethodDef method, CilBody body, IList result, byte[] data) { try { using (var reader = new PdbCustomDebugInfoReader(method, body, MemoryImageStream.Create(data))) reader.Read(result); } catch (ArgumentException) { } catch (OutOfMemoryException) { } catch (IOException) { } } readonly ModuleDef module; readonly TypeDef typeOpt; readonly CilBody bodyOpt; readonly GenericParamContext gpContext; readonly IBinaryReader reader; PdbCustomDebugInfoReader(MethodDef method, CilBody body, IBinaryReader reader) { module = method.Module; typeOpt = method.DeclaringType; bodyOpt = body; gpContext = GenericParamContext.Create(method); this.reader = reader; } void Read(IList result) { if (reader.Length < 4) return; int version = reader.ReadByte(); Debug.Assert(version == CustomDebugInfoConstants.Version); if (version != CustomDebugInfoConstants.Version) return; int count = reader.ReadByte(); reader.Position += 2; while (reader.Position + 8 <= reader.Length) { int recVersion = reader.ReadByte(); Debug.Assert(recVersion == CustomDebugInfoConstants.RecordVersion); var recKind = (PdbCustomDebugInfoKind)reader.ReadByte(); reader.Position++; int alignmentSize = reader.ReadByte(); int recSize = reader.ReadInt32(); if (recSize < 8 || reader.Position - 8 + (uint)recSize > reader.Length) return; if (recKind <= PdbCustomDebugInfoKind.DynamicLocals) alignmentSize = 0; if (alignmentSize > 3) return; var nextRecPos = reader.Position - 8 + recSize; if (recVersion == CustomDebugInfoConstants.RecordVersion) { var recPosEnd = reader.Position - 8 + recSize - alignmentSize; var cdi = ReadRecord(recKind, recPosEnd); Debug.Assert(cdi != null); Debug.Assert(reader.Position <= recPosEnd); if (reader.Position > recPosEnd) return; if (cdi != null) { Debug.Assert(cdi.Kind == recKind); result.Add(cdi); } } reader.Position = nextRecPos; } } PdbCustomDebugInfo ReadRecord(PdbCustomDebugInfoKind recKind, long recPosEnd) { IMethodDefOrRef method; byte[] data; Local local; int count; int localIndex; switch (recKind) { case PdbCustomDebugInfoKind.UsingGroups: count = reader.ReadUInt16(); if (count < 0) return null; var usingCountRec = new PdbUsingGroupsCustomDebugInfo(count); for (int i = 0; i < count; i++) usingCountRec.UsingCounts.Add(reader.ReadUInt16()); return usingCountRec; case PdbCustomDebugInfoKind.ForwardMethodInfo: method = module.ResolveToken(reader.ReadUInt32(), gpContext) as IMethodDefOrRef; if (method == null) return null; return new PdbForwardMethodInfoCustomDebugInfo(method); case PdbCustomDebugInfoKind.ForwardModuleInfo: method = module.ResolveToken(reader.ReadUInt32(), gpContext) as IMethodDefOrRef; if (method == null) return null; return new PdbForwardModuleInfoCustomDebugInfo(method); case PdbCustomDebugInfoKind.StateMachineHoistedLocalScopes: if (bodyOpt == null) return null; count = reader.ReadInt32(); if (count < 0) return null; var smScope = new PdbStateMachineHoistedLocalScopesCustomDebugInfo(count); for (int i = 0; i < count; i++) { uint startOffset = reader.ReadUInt32(); uint endOffset = reader.ReadUInt32(); if (startOffset > endOffset) return null; // Try to detect synthesized locals, whose start==end==0. The problem is that endOffset // read from the PDB is inclusive (add 1 to get 'end'), so a synthesized local and a // local at [0, 1) will be encoded the same {0, 0}. if (endOffset == 0) smScope.Scopes.Add(new StateMachineHoistedLocalScope()); else { var start = GetInstruction(startOffset); var end = GetInstruction(endOffset + 1); if (start == null) return null; smScope.Scopes.Add(new StateMachineHoistedLocalScope(start, end)); } } return smScope; case PdbCustomDebugInfoKind.StateMachineTypeName: var name = ReadUnicodeZ(recPosEnd, needZeroChar: true); if (name == null) return null; var type = GetNestedType(name); if (type == null) return null; return new PdbStateMachineTypeNameCustomDebugInfo(type); case PdbCustomDebugInfoKind.DynamicLocals: if (bodyOpt == null) return null; count = reader.ReadInt32(); const int dynLocalRecSize = 64 + 4 + 4 + 2 * 64; if (reader.Position + (long)(uint)count * dynLocalRecSize > recPosEnd) return null; var dynLocListRec = new PdbDynamicLocalsCustomDebugInfo(count); for (int i = 0; i < count; i++) { reader.Position += 64; int flagsCount = reader.ReadInt32(); if ((uint)flagsCount > 64) return null; var dynLocRec = new PdbDynamicLocal(flagsCount); var afterPos = reader.Position; reader.Position -= 64 + 4; for (int j = 0; j < flagsCount; j++) dynLocRec.Flags.Add(reader.ReadByte()); reader.Position = afterPos; localIndex = reader.ReadInt32(); // 'const' locals have index -1 but they're encoded as 0 by Roslyn if (localIndex != 0 && (uint)localIndex >= (uint)bodyOpt.Variables.Count) return null; var nameEndPos = reader.Position + 2 * 64; name = ReadUnicodeZ(nameEndPos, needZeroChar: false); reader.Position = nameEndPos; local = localIndex < bodyOpt.Variables.Count ? bodyOpt.Variables[localIndex] : null; // Roslyn writes 0 to localIndex if it's a 'const' local, try to undo that now if (localIndex == 0 && local != null && local.Name != name) local = null; if (local != null && local.Name == name) name = null; dynLocRec.Name = name; dynLocRec.Local = local; dynLocListRec.Locals.Add(dynLocRec); } return dynLocListRec; case PdbCustomDebugInfoKind.EditAndContinueLocalSlotMap: data = reader.ReadBytes((int)(recPosEnd - reader.Position)); return new PdbEditAndContinueLocalSlotMapCustomDebugInfo(data); case PdbCustomDebugInfoKind.EditAndContinueLambdaMap: data = reader.ReadBytes((int)(recPosEnd - reader.Position)); return new PdbEditAndContinueLambdaMapCustomDebugInfo(data); case PdbCustomDebugInfoKind.TupleElementNames: if (bodyOpt == null) return null; count = reader.ReadInt32(); if (count < 0) return null; var tupleListRec = new PdbTupleElementNamesCustomDebugInfo(count); for (int i = 0; i < count; i++) { int nameCount = reader.ReadInt32(); if ((uint)nameCount >= 10000) return null; var tupleInfo = new PdbTupleElementNames(nameCount); for (int j = 0; j < nameCount; j++) { var s = ReadUTF8Z(recPosEnd); if (s == null) return null; tupleInfo.TupleElementNames.Add(s); } localIndex = reader.ReadInt32(); uint scopeStart = reader.ReadUInt32(); uint scopeEnd = reader.ReadUInt32(); name = ReadUTF8Z(recPosEnd); if (name == null) return null; Debug.Assert(localIndex >= -1); // -1 = 'const' local. Only 'const' locals have a scope Debug.Assert((localIndex == -1) ^ (scopeStart == 0 && scopeEnd == 0)); if (localIndex == -1) { local = null; tupleInfo.ScopeStart = GetInstruction(scopeStart); tupleInfo.ScopeEnd = GetInstruction(scopeEnd); if (tupleInfo.ScopeStart == null) return null; } else { if ((uint)localIndex >= (uint)bodyOpt.Variables.Count) return null; local = bodyOpt.Variables[localIndex]; } if (local != null && local.Name == name) name = null; tupleInfo.Local = local; tupleInfo.Name = name; tupleListRec.Names.Add(tupleInfo); } return tupleListRec; default: Debug.Fail("Unknown custom debug info kind: 0x" + ((int)recKind).ToString("X")); data = reader.ReadBytes((int)(recPosEnd - reader.Position)); return new PdbUnknownCustomDebugInfo(recKind, data); } } TypeDef GetNestedType(string name) { if (typeOpt == null) return null; foreach (var type in typeOpt.NestedTypes.GetSafeEnumerable()) { if (UTF8String.IsNullOrEmpty(type.Namespace)) { if (type.Name == name) return type; var typeName = type.Name.String; if (typeName.StartsWith(name) && typeName.Length >= name.Length + 2) { int i = name.Length; if (typeName[i] == '`') { Debug.Assert(i + 1 < typeName.Length); bool ok = true; i++; while (i < typeName.Length) { if (!char.IsDigit(typeName[i])) { ok = false; break; } i++; } if (ok) return type; } } } } return null; } string ReadUnicodeZ(long recPosEnd, bool needZeroChar) { var sb = new StringBuilder(); for (;;) { if (reader.Position >= recPosEnd) return needZeroChar ? null : sb.ToString(); var c = (char)reader.ReadUInt16(); if (c == 0) return sb.ToString(); sb.Append(c); } } string ReadUTF8Z(long recPosEnd) { if (reader.Position > recPosEnd) return null; var bytes = reader.ReadBytesUntilByte(0); if (bytes == null) return null; var s = Encoding.UTF8.GetString(bytes); reader.Position++; return s; } Instruction GetInstruction(uint offset) { var instructions = bodyOpt.Instructions; int lo = 0, hi = instructions.Count - 1; while (lo <= hi && hi != -1) { int i = (lo + hi) / 2; var instr = instructions[i]; if (instr.Offset == offset) return instr; if (offset < instr.Offset) hi = i - 1; else lo = i + 1; } return null; } public void Dispose() { reader.Dispose(); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/WindowsPdb/PdbCustomDebugInfoWriter.cs000066400000000000000000000300101325033663500253370ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info // C# & Visual Basic compiler's Custom Debug Info is "documented" in source code only, see Roslyn classes: // CustomDebugInfoReader, CustomDebugInfoWriter, CustomDebugInfoEncoder using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; using dnlib.DotNet.Emit; using dnlib.DotNet.Writer; namespace dnlib.DotNet.Pdb.WindowsPdb { sealed class PdbCustomDebugInfoWriterContext { public ILogger Logger; public readonly MemoryStream MemoryStream; public readonly BinaryWriter Writer; public readonly Dictionary InstructionToOffsetDict; public PdbCustomDebugInfoWriterContext() { MemoryStream = new MemoryStream(); Writer = new BinaryWriter(MemoryStream); InstructionToOffsetDict = new Dictionary(); } } /// /// Writes custom debug infos produced by the C# and Visual Basic compilers. They're stored in PDB files /// as PDB method custom attributes with the name "MD2". /// struct PdbCustomDebugInfoWriter { readonly MetaData metaData; readonly MethodDef method; readonly ILogger logger; readonly MemoryStream memoryStream; readonly BinaryWriter writer; readonly Dictionary instructionToOffsetDict; uint bodySize; bool instructionToOffsetDictInitd; /// /// Returns the raw custom debug info or null if there was an error /// /// Metadata /// Writer context /// Method /// Custom debug infos to write /// public static byte[] Write(MetaData metaData, MethodDef method, PdbCustomDebugInfoWriterContext context, IList customDebugInfos) { var writer = new PdbCustomDebugInfoWriter(metaData, method, context); return writer.Write(customDebugInfos); } PdbCustomDebugInfoWriter(MetaData metaData, MethodDef method, PdbCustomDebugInfoWriterContext context) { this.metaData = metaData; this.method = method; this.logger = context.Logger; this.memoryStream = context.MemoryStream; this.writer = context.Writer; this.instructionToOffsetDict = context.InstructionToOffsetDict; this.bodySize = 0; this.instructionToOffsetDictInitd = false; memoryStream.SetLength(0); memoryStream.Position = 0; } void InitializeInstructionDictionary() { Debug.Assert(!instructionToOffsetDictInitd); instructionToOffsetDict.Clear(); var body = method.Body; if (body == null) return; var instrs = body.Instructions; uint offset = 0; for (int i = 0; i < instrs.Count; i++) { var instr = instrs[i]; instructionToOffsetDict[instr] = offset; offset += (uint)instr.GetSize(); } bodySize = offset; instructionToOffsetDictInitd = true; } uint GetInstructionOffset(Instruction instr, bool nullIsEndOfMethod) { if (!instructionToOffsetDictInitd) InitializeInstructionDictionary(); if (instr == null) { if (nullIsEndOfMethod) return bodySize; Error("Instruction is null"); return uint.MaxValue; } uint offset; if (instructionToOffsetDict.TryGetValue(instr, out offset)) return offset; Error("Instruction is missing in body but it's still being referenced by PDB data. Method {0} (0x{1:X8}), instruction: {2}", method, method.MDToken.Raw, instr); return uint.MaxValue; } void Error(string message, params object[] args) { logger.Log(this, LoggerEvent.Error, message, args); } byte[] Write(IList customDebugInfos) { if (customDebugInfos.Count == 0) return null; if (customDebugInfos.Count > byte.MaxValue) { Error("Too many custom debug infos. Count must be <= 255"); return null; } writer.Write((byte)CustomDebugInfoConstants.Version); writer.Write((byte)customDebugInfos.Count); writer.Write((ushort)0); for (int i = 0; i < customDebugInfos.Count; i++) { var info = customDebugInfos[i]; if (info == null) { Error("Custom debug info is null"); return null; } if ((uint)info.Kind > byte.MaxValue) { Error("Invalid custom debug info kind"); return null; } var recordPos = writer.BaseStream.Position; writer.Write((byte)CustomDebugInfoConstants.RecordVersion); writer.Write((byte)info.Kind); writer.Write((ushort)0); writer.Write((uint)0); int count, j, k; uint token; switch (info.Kind) { case PdbCustomDebugInfoKind.UsingGroups: var usingRec = info as PdbUsingGroupsCustomDebugInfo; if (usingRec == null) { Error("Unsupported custom debug info type {0}", info.GetType()); return null; } count = usingRec.UsingCounts.Count; if (count > ushort.MaxValue) { Error("UsingCounts contains more than 0xFFFF elements"); return null; } writer.Write((ushort)count); for (j = 0; j < count; j++) writer.Write(usingRec.UsingCounts[j]); break; case PdbCustomDebugInfoKind.ForwardMethodInfo: var fwdMethodRec = info as PdbForwardMethodInfoCustomDebugInfo; if (fwdMethodRec == null) { Error("Unsupported custom debug info type {0}", info.GetType()); return null; } token = GetMethodToken(fwdMethodRec.Method); if (token == 0) return null; writer.Write(token); break; case PdbCustomDebugInfoKind.ForwardModuleInfo: var fwdModRec = info as PdbForwardModuleInfoCustomDebugInfo; if (fwdModRec == null) { Error("Unsupported custom debug info type {0}", info.GetType()); return null; } token = GetMethodToken(fwdModRec.Method); if (token == 0) return null; writer.Write(token); break; case PdbCustomDebugInfoKind.StateMachineHoistedLocalScopes: var smLocalScopesRec = info as PdbStateMachineHoistedLocalScopesCustomDebugInfo; if (smLocalScopesRec == null) { Error("Unsupported custom debug info type {0}", info.GetType()); return null; } count = smLocalScopesRec.Scopes.Count; writer.Write(count); for (j = 0; j < count; j++) { var scope = smLocalScopesRec.Scopes[j]; if (scope.IsSynthesizedLocal) { writer.Write(0); writer.Write(0); } else { writer.Write(GetInstructionOffset(scope.Start, nullIsEndOfMethod: false)); writer.Write(GetInstructionOffset(scope.End, nullIsEndOfMethod: true) - 1); } } break; case PdbCustomDebugInfoKind.StateMachineTypeName: var smTypeRec = info as PdbStateMachineTypeNameCustomDebugInfo; if (smTypeRec == null) { Error("Unsupported custom debug info type {0}", info.GetType()); return null; } var type = smTypeRec.Type; if (type == null) { Error("State machine type is null"); return null; } WriteUnicodeZ(MetadataNameToRoslynName(type.Name)); break; case PdbCustomDebugInfoKind.DynamicLocals: var dynLocListRec = info as PdbDynamicLocalsCustomDebugInfo; if (dynLocListRec == null) { Error("Unsupported custom debug info type {0}", info.GetType()); return null; } count = dynLocListRec.Locals.Count; writer.Write(count); for (j = 0; j < count; j++) { var dynLoc = dynLocListRec.Locals[j]; if (dynLoc == null) { Error("Dynamic local is null"); return null; } if (dynLoc.Flags.Count > 64) { Error("Dynamic local flags is longer than 64 bytes"); return null; } var name = dynLoc.Name; if (name == null) name = string.Empty; if (name.Length > 64) { Error("Dynamic local name is longer than 64 chars"); return null; } if (name.IndexOf('\0') >= 0) { Error("Dynamic local name contains a NUL char"); return null; } for (k = 0; k < dynLoc.Flags.Count; k++) writer.Write(dynLoc.Flags[k]); while (k++ < 64) writer.Write((byte)0); writer.Write(dynLoc.Flags.Count); if (dynLoc.Local == null) writer.Write(0); else writer.Write(dynLoc.Local.Index); for (k = 0; k < name.Length; k++) writer.Write((ushort)name[k]); while (k++ < 64) writer.Write((ushort)0); } break; case PdbCustomDebugInfoKind.EditAndContinueLocalSlotMap: var encLocalMapRec = info as PdbEditAndContinueLocalSlotMapCustomDebugInfo; if (encLocalMapRec == null) { Error("Unsupported custom debug info type {0}", info.GetType()); return null; } writer.Write(encLocalMapRec.Data); break; case PdbCustomDebugInfoKind.EditAndContinueLambdaMap: var encLambdaRec = info as PdbEditAndContinueLambdaMapCustomDebugInfo; if (encLambdaRec == null) { Error("Unsupported custom debug info type {0}", info.GetType()); return null; } writer.Write(encLambdaRec.Data); break; case PdbCustomDebugInfoKind.TupleElementNames: var tupleListRec = info as PdbTupleElementNamesCustomDebugInfo; if (tupleListRec == null) { Error("Unsupported custom debug info type {0}", info.GetType()); return null; } count = tupleListRec.Names.Count; writer.Write(count); for (j = 0; j < count; j++) { var tupleInfo = tupleListRec.Names[j]; if (tupleInfo == null) { Error("Tuple name info is null"); return null; } writer.Write(tupleInfo.TupleElementNames.Count); for (k = 0; k < tupleInfo.TupleElementNames.Count; k++) WriteUTF8Z(tupleInfo.TupleElementNames[k]); if (tupleInfo.Local == null) { writer.Write(-1); writer.Write(GetInstructionOffset(tupleInfo.ScopeStart, nullIsEndOfMethod: false)); writer.Write(GetInstructionOffset(tupleInfo.ScopeEnd, nullIsEndOfMethod: true)); } else { writer.Write(tupleInfo.Local.Index); writer.Write(0L); } WriteUTF8Z(tupleInfo.Name); } break; default: var unkRec = info as PdbUnknownCustomDebugInfo; if (unkRec == null) { Error("Unsupported custom debug info class {0}", info.GetType()); return null; } writer.Write(unkRec.Data); break; } var pos = writer.BaseStream.Position; var recLen = (pos - recordPos); var alignedLen = (recLen + 3) & ~3; if (alignedLen > uint.MaxValue) { Error("Custom debug info record is too big"); return null; } writer.BaseStream.Position = recordPos + 3; if (info.Kind <= PdbCustomDebugInfoKind.DynamicLocals) writer.Write((byte)0); else writer.Write((byte)(alignedLen - recLen)); writer.Write((uint)alignedLen); writer.BaseStream.Position = pos; while (writer.BaseStream.Position < recordPos + alignedLen) writer.Write((byte)0); } return memoryStream.ToArray(); } string MetadataNameToRoslynName(string name) { if (name == null) return name; int index = name.LastIndexOf('`'); if (index < 0) return name; return name.Substring(0, index); } void WriteUnicodeZ(string s) { if (s == null) { Error("String is null"); return; } if (s.IndexOf('\0') >= 0) { Error("String contains a NUL char: {0}", s); return; } for (int i = 0; i < s.Length; i++) writer.Write((ushort)s[i]); writer.Write((ushort)0); } void WriteUTF8Z(string s) { if (s == null) { Error("String is null"); return; } if (s.IndexOf('\0') >= 0) { Error("String contains a NUL char: {0}", s); return; } writer.Write(Encoding.UTF8.GetBytes(s)); writer.Write((byte)0); } uint GetMethodToken(IMethodDefOrRef method) { if (method == null) { Error("Method is null"); return 0; } var md = method as MethodDef; if (md != null) { uint rid = metaData.GetRid(md); if (rid == 0) { Error("Method {0} ({1:X8}) is not defined in this module ({2})", method, method.MDToken.Raw, metaData.Module); return 0; } return new MDToken(md.MDToken.Table, rid).Raw; } var mr = method as MemberRef; if (mr != null && mr.IsMethodRef) return metaData.GetToken(mr).Raw; Error("Not a method"); return 0; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/WindowsPdb/PseudoCustomDebugInfoFactory.cs000066400000000000000000000051241325033663500262340ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Diagnostics; using dnlib.DotNet.Emit; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb.Symbols; namespace dnlib.DotNet.Pdb.WindowsPdb { static class PseudoCustomDebugInfoFactory { public static PdbAsyncMethodCustomDebugInfo TryCreateAsyncMethod(ModuleDef module, MethodDef method, CilBody body, int asyncKickoffMethod, IList asyncStepInfos, uint? asyncCatchHandlerILOffset) { var kickoffToken = new MDToken(asyncKickoffMethod); if (kickoffToken.Table != Table.Method) return null; var kickoffMethod = module.ResolveToken(kickoffToken) as MethodDef; var asyncMethod = new PdbAsyncMethodCustomDebugInfo(asyncStepInfos.Count); asyncMethod.KickoffMethod = kickoffMethod; if (asyncCatchHandlerILOffset != null) { asyncMethod.CatchHandlerInstruction = GetInstruction(body, asyncCatchHandlerILOffset.Value); Debug.Assert(asyncMethod.CatchHandlerInstruction != null); } foreach (var rawInfo in asyncStepInfos) { var yieldInstruction = GetInstruction(body, rawInfo.YieldOffset); Debug.Assert(yieldInstruction != null); if (yieldInstruction == null) continue; MethodDef breakpointMethod; Instruction breakpointInstruction; if (method.MDToken.Raw == rawInfo.BreakpointMethod) { breakpointMethod = method; breakpointInstruction = GetInstruction(body, rawInfo.BreakpointOffset); } else { var breakpointMethodToken = new MDToken(rawInfo.BreakpointMethod); Debug.Assert(breakpointMethodToken.Table == Table.Method); if (breakpointMethodToken.Table != Table.Method) continue; breakpointMethod = module.ResolveToken(breakpointMethodToken) as MethodDef; Debug.Assert(breakpointMethod != null); if (breakpointMethod == null) continue; breakpointInstruction = GetInstruction(breakpointMethod.Body, rawInfo.BreakpointOffset); } Debug.Assert(breakpointInstruction != null); if (breakpointInstruction == null) continue; asyncMethod.StepInfos.Add(new PdbAsyncStepInfo(yieldInstruction, breakpointMethod, breakpointInstruction)); } return asyncMethod; } static Instruction GetInstruction(CilBody body, uint offset) { if (body == null) return null; var instructions = body.Instructions; int lo = 0, hi = instructions.Count - 1; while (lo <= hi && hi != -1) { int i = (lo + hi) / 2; var instr = instructions[i]; if (instr.Offset == offset) return instr; if (offset < instr.Offset) hi = i - 1; else lo = i + 1; } return null; } } } dnlib-2.1_VS2010/src/DotNet/Pdb/WindowsPdb/SymbolWriterCreator.cs000066400000000000000000000017121325033663500244500ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; namespace dnlib.DotNet.Pdb.WindowsPdb { /// /// Creates a /// static class SymbolWriterCreator { /// /// Creates a new instance /// /// PDB file name /// A new instance public static ISymbolWriter2 Create(string pdbFileName) { return Dss.SymbolWriterCreator.Create(pdbFileName); } /// /// Creates a new instance /// /// PDB output stream /// PDB file name /// A new instance public static ISymbolWriter2 Create(Stream pdbStream, string pdbFileName) { return Dss.SymbolWriterCreator.Create(pdbStream, pdbFileName); } } } dnlib-2.1_VS2010/src/DotNet/Pdb/WindowsPdb/WindowsPdbWriter.cs000066400000000000000000000363061325033663500237520ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.SymbolStore; using dnlib.DotNet.Emit; using dnlib.DotNet.Writer; namespace dnlib.DotNet.Pdb.WindowsPdb { /// /// PDB writer /// /// This class is not thread safe because it's a writer class public sealed class WindowsPdbWriter : IDisposable { ISymbolWriter2 writer; ISymbolWriter3 writer3; readonly PdbState pdbState; readonly ModuleDef module; readonly MetaData metaData; readonly Dictionary pdbDocs = new Dictionary(); readonly SequencePointHelper seqPointsHelper = new SequencePointHelper(); readonly Dictionary instrToOffset; readonly PdbCustomDebugInfoWriterContext customDebugInfoWriterContext; readonly int localsEndScopeIncValue; /// /// Gets/sets the logger /// public ILogger Logger { get; set; } /// /// Constructor /// /// Symbol writer, it should implement /// PDB state /// Meta data public WindowsPdbWriter(ISymbolWriter2 writer, PdbState pdbState, MetaData metaData) : this(pdbState, metaData) { if (writer == null) throw new ArgumentNullException("writer"); if (pdbState == null) throw new ArgumentNullException("pdbState"); if (metaData == null) throw new ArgumentNullException("metaData"); this.writer = writer; this.writer3 = writer as ISymbolWriter3; Debug.Assert(writer3 != null, "Symbol writer doesn't implement interface ISymbolWriter3"); writer.Initialize(metaData); } /// /// Constructor /// /// Symbol writer /// PDB state /// Meta data public WindowsPdbWriter(ISymbolWriter3 writer, PdbState pdbState, MetaData metaData) : this(pdbState, metaData) { if (writer == null) throw new ArgumentNullException("writer"); if (pdbState == null) throw new ArgumentNullException("pdbState"); if (metaData == null) throw new ArgumentNullException("metaData"); this.writer = writer; this.writer3 = writer; writer.Initialize(metaData); } WindowsPdbWriter(PdbState pdbState, MetaData metaData) { this.pdbState = pdbState; this.metaData = metaData; this.module = metaData.Module; this.instrToOffset = new Dictionary(); this.customDebugInfoWriterContext = new PdbCustomDebugInfoWriterContext(); this.localsEndScopeIncValue = pdbState.Compiler == Compiler.VisualBasic ? 1 : 0; } /// /// Adds if it doesn't exist /// /// PDB document /// A instance ISymbolDocumentWriter Add(PdbDocument pdbDoc) { ISymbolDocumentWriter docWriter; if (pdbDocs.TryGetValue(pdbDoc, out docWriter)) return docWriter; docWriter = writer.DefineDocument(pdbDoc.Url, pdbDoc.Language, pdbDoc.LanguageVendor, pdbDoc.DocumentType); docWriter.SetCheckSum(pdbDoc.CheckSumAlgorithmId, pdbDoc.CheckSum); pdbDocs.Add(pdbDoc, docWriter); return docWriter; } /// /// Writes the PDB file /// public void Write() { writer.SetUserEntryPoint(new SymbolToken(GetUserEntryPointToken())); var cdiBuilder = new List(); foreach (var type in module.GetTypes()) { if (type == null) continue; foreach (var method in type.Methods) { if (method == null) continue; if (!ShouldAddMethod(method)) continue; Write(method, cdiBuilder); } } } bool ShouldAddMethod(MethodDef method) { var body = method.Body; if (body == null) return false; if (body.HasPdbMethod) return true; foreach (var local in body.Variables) { // Don't check whether it's the empty string. Only check for null. if (local.Name != null) return true; if (local.Attributes != 0) return true; } foreach (var instr in body.Instructions) { if (instr.SequencePoint != null) return true; } return false; } sealed class SequencePointHelper { readonly Dictionary checkedPdbDocs = new Dictionary(); int[] instrOffsets = new int[0]; int[] startLines; int[] startColumns; int[] endLines; int[] endColumns; public void Write(WindowsPdbWriter pdbWriter, IList instrs) { checkedPdbDocs.Clear(); while (true) { PdbDocument currPdbDoc = null; bool otherDocsAvailable = false; int index = 0, instrOffset = 0; Instruction instr = null; for (int i = 0; i < instrs.Count; i++, instrOffset += instr.GetSize()) { instr = instrs[i]; var seqp = instr.SequencePoint; if (seqp == null || seqp.Document == null) continue; if (checkedPdbDocs.ContainsKey(seqp.Document)) continue; if (currPdbDoc == null) currPdbDoc = seqp.Document; else if (currPdbDoc != seqp.Document) { otherDocsAvailable = true; continue; } if (index >= instrOffsets.Length) { int newSize = index * 2; if (newSize < 64) newSize = 64; Array.Resize(ref instrOffsets, newSize); Array.Resize(ref startLines, newSize); Array.Resize(ref startColumns, newSize); Array.Resize(ref endLines, newSize); Array.Resize(ref endColumns, newSize); } instrOffsets[index] = instrOffset; startLines[index] = seqp.StartLine; startColumns[index] = seqp.StartColumn; endLines[index] = seqp.EndLine; endColumns[index] = seqp.EndColumn; index++; } if (index != 0) pdbWriter.writer.DefineSequencePoints(pdbWriter.Add(currPdbDoc), (uint)index, instrOffsets, startLines, startColumns, endLines, endColumns); if (!otherDocsAvailable) break; if (currPdbDoc != null) checkedPdbDocs.Add(currPdbDoc, true); } } } struct CurrentMethod { readonly WindowsPdbWriter pdbWriter; public readonly MethodDef Method; readonly Dictionary toOffset; public readonly uint BodySize; public CurrentMethod(WindowsPdbWriter pdbWriter, MethodDef method, Dictionary toOffset) { this.pdbWriter = pdbWriter; Method = method; this.toOffset = toOffset; toOffset.Clear(); uint offset = 0; foreach (var instr in method.Body.Instructions) { toOffset[instr] = offset; offset += (uint)instr.GetSize(); } BodySize = offset; } public int GetOffset(Instruction instr) { if (instr == null) return (int)BodySize; uint offset; if (toOffset.TryGetValue(instr, out offset)) return (int)offset; pdbWriter.Error("Instruction was removed from the body but is referenced from PdbScope: {0}", instr); return (int)BodySize; } } void Write(MethodDef method, List cdiBuilder) { uint rid = metaData.GetRid(method); if (rid == 0) { Error("Method {0} ({1:X8}) is not defined in this module ({2})", method, method.MDToken.Raw, module); return; } var info = new CurrentMethod(this, method, instrToOffset); var body = method.Body; var symbolToken = new SymbolToken((int)new MDToken(MD.Table.Method, metaData.GetRid(method)).Raw); writer.OpenMethod(symbolToken); seqPointsHelper.Write(this, info.Method.Body.Instructions); var pdbMethod = body.PdbMethod; if (pdbMethod == null) body.PdbMethod = pdbMethod = new PdbMethod(); var scope = pdbMethod.Scope; if (scope == null) pdbMethod.Scope = scope = new PdbScope(); if (scope.Namespaces.Count == 0 && scope.Variables.Count == 0 && scope.Constants.Count == 0) { if (scope.Scopes.Count == 0) { // We must open at least one sub scope (the sym writer creates the 'method' scope // which covers the whole method) or the native PDB reader will fail to read all // sequence points. writer.OpenScope(0); writer.CloseScope((int)info.BodySize); } else { foreach (var childScope in scope.Scopes) WriteScope(ref info, childScope, 0); } } else { Debug.Fail("Root scope isn't empty"); WriteScope(ref info, scope, 0); } PdbAsyncMethodCustomDebugInfo asyncMethod; GetPseudoCustomDebugInfos(method.CustomDebugInfos, cdiBuilder, out asyncMethod); if (cdiBuilder.Count != 0) { customDebugInfoWriterContext.Logger = GetLogger(); var cdiData = PdbCustomDebugInfoWriter.Write(metaData, method, customDebugInfoWriterContext, cdiBuilder); if (cdiData != null) writer.SetSymAttribute(symbolToken, "MD2", cdiData); } if (asyncMethod != null) { if (writer3 == null || !writer3.SupportsAsyncMethods) Error("PDB symbol writer doesn't support writing async methods"); else WriteAsyncMethod(ref info, asyncMethod); } writer.CloseMethod(); } void GetPseudoCustomDebugInfos(IList customDebugInfos, List cdiBuilder, out PdbAsyncMethodCustomDebugInfo asyncMethod) { cdiBuilder.Clear(); asyncMethod = null; foreach (var cdi in customDebugInfos) { switch (cdi.Kind) { case PdbCustomDebugInfoKind.AsyncMethod: if (asyncMethod != null) Error("Duplicate async method custom debug info"); else asyncMethod = (PdbAsyncMethodCustomDebugInfo)cdi; break; default: if ((uint)cdi.Kind > byte.MaxValue) Error("Custom debug info {0} isn't supported by Windows PDB files", cdi.Kind); else cdiBuilder.Add(cdi); break; } } } uint GetMethodToken(MethodDef method) { uint rid = metaData.GetRid(method); if (rid == 0) Error("Method {0} ({1:X8}) is not defined in this module ({2})", method, method.MDToken.Raw, module); return new MDToken(MD.Table.Method, rid).Raw; } void WriteAsyncMethod(ref CurrentMethod info, PdbAsyncMethodCustomDebugInfo asyncMethod) { if (asyncMethod.KickoffMethod == null) { Error("KickoffMethod is null"); return; } uint kickoffMethod = GetMethodToken(asyncMethod.KickoffMethod); writer3.DefineKickoffMethod(kickoffMethod); if (asyncMethod.CatchHandlerInstruction != null) { int catchHandlerILOffset = info.GetOffset(asyncMethod.CatchHandlerInstruction); writer3.DefineCatchHandlerILOffset((uint)catchHandlerILOffset); } var stepInfos = asyncMethod.StepInfos; var yieldOffsets = new uint[stepInfos.Count]; var breakpointOffset = new uint[stepInfos.Count]; var breakpointMethods = new uint[stepInfos.Count]; for (int i = 0; i < yieldOffsets.Length; i++) { var stepInfo = stepInfos[i]; if (stepInfo.YieldInstruction == null) { Error("YieldInstruction is null"); return; } if (stepInfo.BreakpointMethod == null) { Error("BreakpointInstruction is null"); return; } if (stepInfo.BreakpointInstruction == null) { Error("BreakpointInstruction is null"); return; } yieldOffsets[i] = (uint)info.GetOffset(stepInfo.YieldInstruction); breakpointOffset[i] = (uint)GetExternalInstructionOffset(ref info, stepInfo.BreakpointMethod, stepInfo.BreakpointInstruction); breakpointMethods[i] = GetMethodToken(stepInfo.BreakpointMethod); } writer3.DefineAsyncStepInfo(yieldOffsets, breakpointOffset, breakpointMethods); } int GetExternalInstructionOffset(ref CurrentMethod info, MethodDef method, Instruction instr) { if (info.Method == method) return info.GetOffset(instr); var body = method.Body; if (body == null) { Error("Method body is null"); return 0; } var instrs = body.Instructions; int offset = 0; for (int i = 0; i < instrs.Count; i++) { var currInstr = instrs[i]; if (currInstr == instr) return offset; offset += currInstr.GetSize(); } if (instr == null) return offset; Error("Async method instruction has been removed but it's still being referenced by PDB info: BP Instruction: {0}, BP Method: {1} (0x{2:X8}), Current Method: {3} (0x{4:X8})", instr, method, method.MDToken.Raw, info.Method, info.Method.MDToken.Raw); return 0; } void WriteScope(ref CurrentMethod info, PdbScope scope, int recursionCounter) { if (recursionCounter >= 1000) { Error("Too many PdbScopes"); return; } int startOffset = info.GetOffset(scope.Start); int endOffset = info.GetOffset(scope.End); writer.OpenScope(startOffset); AddLocals(info.Method, scope.Variables, (uint)startOffset, (uint)endOffset); if (scope.Constants.Count > 0) { if (writer3 == null) Error("Symbol writer doesn't implement ISymbolWriter3: no constants can be written to the PDB file"); else { var constants = scope.Constants; var sig = new FieldSig(); for (int i = 0; i < constants.Count; i++) { var constant = constants[i]; sig.Type = constant.Type; var token = metaData.GetToken(sig); writer3.DefineConstant2(constant.Name, constant.Value ?? 0, token.Raw); } } } foreach (var ns in scope.Namespaces) writer.UsingNamespace(ns); foreach (var childScope in scope.Scopes) WriteScope(ref info, childScope, recursionCounter + 1); writer.CloseScope(startOffset == 0 && endOffset == info.BodySize ? endOffset : endOffset - localsEndScopeIncValue); } void AddLocals(MethodDef method, IList locals, uint startOffset, uint endOffset) { if (locals.Count == 0) return; uint token = metaData.GetLocalVarSigToken(method); if (token == 0) { Error("Method {0} ({1:X8}) has no local signature token", method, method.MDToken.Raw); return; } foreach (var local in locals) { uint attrs = GetPdbLocalFlags(local.Attributes); if (attrs == 0 && local.Name == null) continue; writer.DefineLocalVariable2(local.Name ?? string.Empty, attrs, token, 1, (uint)local.Index, 0, 0, startOffset, endOffset); } } static uint GetPdbLocalFlags(PdbLocalAttributes attributes) { if ((attributes & PdbLocalAttributes.DebuggerHidden) != 0) return (uint)CorSymVarFlag.VAR_IS_COMP_GEN; return 0; } int GetUserEntryPointToken() { var ep = pdbState.UserEntryPoint; if (ep == null) return 0; uint rid = metaData.GetRid(ep); if (rid == 0) { Error("PDB user entry point method {0} ({1:X8}) is not defined in this module ({2})", ep, ep.MDToken.Raw, module); return 0; } return new MDToken(MD.Table.Method, rid).ToInt32(); } /// /// Gets the and debug data that should be written to /// the PE file. /// /// Updated with new values /// Debug data public byte[] GetDebugInfo(out IMAGE_DEBUG_DIRECTORY idd) { return writer.GetDebugInfo(out idd); } /// /// Closes the PDB writer /// public void Close() { writer.Close(); } ILogger GetLogger() { return Logger ?? DummyLogger.ThrowModuleWriterExceptionOnErrorInstance; } void Error(string message, params object[] args) { GetLogger().Log(this, LoggerEvent.Error, message, args); } /// public void Dispose() { if (writer != null) Close(); writer = null; } } } dnlib-2.1_VS2010/src/DotNet/PropertyAttributes.cs000066400000000000000000000007671325033663500216050ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// Property attributes, see CorHdr.h/CorPropertyAttr /// [Flags] public enum PropertyAttributes : ushort { /// property is special. Name describes how. SpecialName = 0x0200, /// Runtime(metadata internal APIs) should check name encoding. RTSpecialName = 0x0400, /// Property has default HasDefault = 0x1000, } } dnlib-2.1_VS2010/src/DotNet/PropertyDef.cs000066400000000000000000000400031325033663500201400ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the Property table /// public abstract class PropertyDef : IHasConstant, IHasCustomAttribute, IHasSemantic, IHasCustomDebugInformation, IFullName, IMemberDef { /// /// The row id in its table /// protected uint rid; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// public MDToken MDToken { get { return new MDToken(Table.Property, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasConstantTag { get { return 2; } } /// public int HasCustomAttributeTag { get { return 9; } } /// public int HasSemanticTag { get { return 1; } } /// /// From column Property.PropFlags /// public PropertyAttributes Attributes { get { return (PropertyAttributes)attributes; } set { attributes = (int)value; } } /// Attributes protected int attributes; /// /// From column Property.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// From column Property.Type /// public CallingConventionSig Type { get { return type; } set { type = value; } } /// protected CallingConventionSig type; /// public Constant Constant { get { if (!constant_isInitialized) InitializeConstant(); return constant; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif constant = value; constant_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected Constant constant; /// protected bool constant_isInitialized; void InitializeConstant() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (constant_isInitialized) return; constant = GetConstant_NoLock(); constant_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual Constant GetConstant_NoLock() { return null; } /// Reset protected void ResetConstant() { constant_isInitialized = false; } /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public int HasCustomDebugInformationTag { get { return 9; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// /// Gets/sets the first getter method. Writing null will clear all get methods. /// public MethodDef GetMethod { get { if (otherMethods == null) InitializePropertyMethods(); return getMethods.Get(0, null); } set { if (otherMethods == null) InitializePropertyMethods(); if (value == null) getMethods.Clear(); else if (getMethods.Count == 0) getMethods.Add(value); else getMethods.Set(0, value); } } /// /// Gets/sets the first setter method. Writing null will clear all set methods. /// public MethodDef SetMethod { get { if (otherMethods == null) InitializePropertyMethods(); return setMethods.Get(0, null); } set { if (otherMethods == null) InitializePropertyMethods(); if (value == null) setMethods.Clear(); else if (setMethods.Count == 0) setMethods.Add(value); else setMethods.Set(0, value); } } /// /// Gets all getter methods /// public ThreadSafe.IList GetMethods { get { if (otherMethods == null) InitializePropertyMethods(); return getMethods; } } /// /// Gets all setter methods /// public ThreadSafe.IList SetMethods { get { if (otherMethods == null) InitializePropertyMethods(); return setMethods; } } /// /// Gets the other methods /// public ThreadSafe.IList OtherMethods { get { if (otherMethods == null) InitializePropertyMethods(); return otherMethods; } } void InitializePropertyMethods() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (otherMethods == null) InitializePropertyMethods_NoLock(); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// /// Initializes , , /// and . /// protected virtual void InitializePropertyMethods_NoLock() { getMethods = ThreadSafeListCreator.Create(); setMethods = ThreadSafeListCreator.Create(); otherMethods = ThreadSafeListCreator.Create(); } /// protected ThreadSafe.IList getMethods; /// protected ThreadSafe.IList setMethods; /// protected ThreadSafe.IList otherMethods; /// Reset , , protected void ResetMethods() { otherMethods = null; } /// /// true if there are no methods attached to this property /// public bool IsEmpty { get { // The first property access initializes the other fields we access here return GetMethods.Count == 0 && setMethods.Count == 0 && otherMethods.Count == 0; } } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// /// true if is not empty /// public bool HasOtherMethods { get { return OtherMethods.Count > 0; } } /// /// true if is not null /// public bool HasConstant { get { return Constant != null; } } /// /// Gets the constant element type or if there's no constant /// public ElementType ElementType { get { var c = Constant; return c == null ? ElementType.End : c.Type; } } /// /// Gets/sets the property sig /// public PropertySig PropertySig { get { return type as PropertySig; } set { type = value; } } /// /// Gets/sets the declaring type (owner type) /// public TypeDef DeclaringType { get { return declaringType2; } set { var currentDeclaringType = DeclaringType2; if (currentDeclaringType == value) return; if (currentDeclaringType != null) currentDeclaringType.Properties.Remove(this); // Will set DeclaringType2 = null if (value != null) value.Properties.Add(this); // Will set DeclaringType2 = value } } /// ITypeDefOrRef IMemberRef.DeclaringType { get { return declaringType2; } } /// /// Called by and should normally not be called by any user /// code. Use instead. Only call this if you must set the /// declaring type without inserting it in the declaring type's method list. /// public TypeDef DeclaringType2 { get { return declaringType2; } set { declaringType2 = value; } } /// protected TypeDef declaringType2; /// public ModuleDef Module { get { var dt = declaringType2; return dt == null ? null : dt.Module; } } /// /// Gets the full name of the property /// public string FullName { get { var dt = declaringType2; return FullNameCreator.PropertyFullName(dt == null ? null : dt.FullName, name, type, null, null); } } bool IIsTypeOrMethod.IsType { get { return false; } } bool IIsTypeOrMethod.IsMethod { get { return false; } } bool IMemberRef.IsField { get { return false; } } bool IMemberRef.IsTypeSpec { get { return false; } } bool IMemberRef.IsTypeRef { get { return false; } } bool IMemberRef.IsTypeDef { get { return false; } } bool IMemberRef.IsMethodSpec { get { return false; } } bool IMemberRef.IsMethodDef { get { return false; } } bool IMemberRef.IsMemberRef { get { return false; } } bool IMemberRef.IsFieldDef { get { return false; } } bool IMemberRef.IsPropertyDef { get { return true; } } bool IMemberRef.IsEventDef { get { return false; } } bool IMemberRef.IsGenericParam { get { return false; } } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyAttributes(bool set, PropertyAttributes 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 IsSpecialName { get { return ((PropertyAttributes)attributes & PropertyAttributes.SpecialName) != 0; } set { ModifyAttributes(value, PropertyAttributes.SpecialName); } } /// /// Gets/sets the bit /// public bool IsRuntimeSpecialName { get { return ((PropertyAttributes)attributes & PropertyAttributes.RTSpecialName) != 0; } set { ModifyAttributes(value, PropertyAttributes.RTSpecialName); } } /// /// Gets/sets the bit /// public bool HasDefault { get { return ((PropertyAttributes)attributes & PropertyAttributes.HasDefault) != 0; } set { ModifyAttributes(value, PropertyAttributes.HasDefault); } } /// public override string ToString() { return FullName; } } /// /// A Property row created by the user and not present in the original .NET file /// public class PropertyDefUser : PropertyDef { /// /// Default constructor /// public PropertyDefUser() { } /// /// Constructor /// /// Name public PropertyDefUser(UTF8String name) : this(name, null) { } /// /// Constructor /// /// Name /// Property signature public PropertyDefUser(UTF8String name, PropertySig sig) : this(name, sig, 0) { } /// /// Constructor /// /// Name /// Property signature /// Flags public PropertyDefUser(UTF8String name, PropertySig sig, PropertyAttributes flags) { this.name = name; this.type = sig; this.attributes = (int)flags; } } /// /// Created from a row in the Property table /// sealed class PropertyDefMD : PropertyDef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; /// public uint OrigRid { get { return origRid; } } /// protected override Constant GetConstant_NoLock() { return readerModule.ResolveConstant(readerModule.MetaData.GetConstantRid(Table.Property, origRid)); } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.Property, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(declaringType2), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this Property row /// Row ID /// If is null /// If is invalid public PropertyDefMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.PropertyTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("Property rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; uint name; uint type = readerModule.TablesStream.ReadPropertyRow(origRid, out this.attributes, out name); this.name = readerModule.StringsStream.ReadNoNull(name); this.declaringType2 = readerModule.GetOwnerType(this); this.type = readerModule.ReadSignature(type, new GenericParamContext(declaringType2)); } internal PropertyDefMD InitializeAll() { MemberMDInitializer.Initialize(Attributes); MemberMDInitializer.Initialize(Name); MemberMDInitializer.Initialize(Type); MemberMDInitializer.Initialize(Constant); MemberMDInitializer.Initialize(CustomAttributes); MemberMDInitializer.Initialize(GetMethod); MemberMDInitializer.Initialize(SetMethod); MemberMDInitializer.Initialize(OtherMethods); MemberMDInitializer.Initialize(DeclaringType); return this; } /// protected override void InitializePropertyMethods_NoLock() { if (otherMethods != null) return; ThreadSafe.IList newOtherMethods; ThreadSafe.IList newGetMethods, newSetMethods; var dt = declaringType2 as TypeDefMD; if (dt == null) { newGetMethods = ThreadSafeListCreator.Create(); newSetMethods = ThreadSafeListCreator.Create(); newOtherMethods = ThreadSafeListCreator.Create(); } else dt.InitializeProperty(this, out newGetMethods, out newSetMethods, out newOtherMethods); getMethods = newGetMethods; setMethods = newSetMethods; // Must be initialized last otherMethods = newOtherMethods; } } } dnlib-2.1_VS2010/src/DotNet/PublicKey.cs000066400000000000000000000040011325033663500175620ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.Threading; namespace dnlib.DotNet { /// /// Represents a public key /// public sealed class PublicKey : PublicKeyBase { const AssemblyHashAlgorithm DEFAULT_ALGORITHM = AssemblyHashAlgorithm.SHA1; PublicKeyToken publicKeyToken; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// /// Gets the /// public override PublicKeyToken Token { get { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (publicKeyToken == null && !IsNullOrEmpty_NoLock) publicKeyToken = AssemblyHash.CreatePublicKeyToken(data); return publicKeyToken; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// public override byte[] Data { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return data; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (data == value) return; data = value; publicKeyToken = null; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Default constructor /// public PublicKey() { } /// /// Constructor /// /// Public key data public PublicKey(byte[] data) : base(data) { } /// /// Constructor /// /// Public key data as a hex string or the string "null" /// to set public key data to null public PublicKey(string hexString) : base(hexString) { } /// public override bool Equals(object obj) { if ((object)this == obj) return true; var other = obj as PublicKey; if (other == null) return false; return Utils.Equals(Data, other.Data); } /// public override int GetHashCode() { return Utils.GetHashCode(Data); } } } dnlib-2.1_VS2010/src/DotNet/PublicKeyBase.cs000066400000000000000000000135631325033663500203720ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Public key / public key token base class /// public abstract class PublicKeyBase { /// /// The key data /// protected byte[] data; /// /// Returns true if is null or empty /// public bool IsNullOrEmpty { get { return IsNullOrEmpty_NoLock; } } /// /// The unlocked version of . /// protected bool IsNullOrEmpty_NoLock { get { return data == null || data.Length == 0; } } /// /// Returns true if is null /// public bool IsNull { get { return Data == null; } } /// /// Gets/sets key data /// public virtual byte[] Data { get { return data; } set { data = value; } } /// /// Gets the /// public abstract PublicKeyToken Token { get; } /// /// Default constructor /// protected PublicKeyBase() { } /// /// Constructor /// /// Key data protected PublicKeyBase(byte[] data) { this.data = data; } /// /// Constructor /// /// Key data as a hex string or the string "null" /// to set key data to null protected PublicKeyBase(string hexString) { this.data = Parse(hexString); } static byte[] Parse(string hexString) { if (hexString == null || hexString == "null") return null; return Utils.ParseBytes(hexString); } /// /// Checks whether a public key or token is null or empty /// /// Public key or token instance public static bool IsNullOrEmpty2(PublicKeyBase a) { return a == null || a.IsNullOrEmpty; } /// /// Returns a /// /// A or a instance public static PublicKeyToken ToPublicKeyToken(PublicKeyBase pkb) { var pkt = pkb as PublicKeyToken; if (pkt != null) return pkt; var pk = pkb as PublicKey; if (pk != null) return pk.Token; return null; } /// /// Compares two s as s /// /// First /// Second /// < 0 if a < b, 0 if a == b, > 0 if a > b public static int TokenCompareTo(PublicKeyBase a, PublicKeyBase b) { if (a == b) return 0; return TokenCompareTo(ToPublicKeyToken(a), ToPublicKeyToken(b)); } /// /// Checks whether two public key tokens are equal /// /// First /// Second /// true if same, false otherwise public static bool TokenEquals(PublicKeyBase a, PublicKeyBase b) { return TokenCompareTo(a, b) == 0; } static readonly byte[] EmptyByteArray = new byte[0]; /// /// Compares two s /// /// First /// Second /// < 0 if a < b, 0 if a == b, > 0 if a > b public static int TokenCompareTo(PublicKeyToken a, PublicKeyToken b) { if (a == b) return 0; return TokenCompareTo(a == null ? null : a.Data, b == null ? null : b.Data); } static int TokenCompareTo(byte[] a, byte[] b) { return Utils.CompareTo(a ?? EmptyByteArray, b ?? EmptyByteArray); } /// /// Checks whether two public key tokens are equal /// /// First /// Second /// true if same, false otherwise public static bool TokenEquals(PublicKeyToken a, PublicKeyToken b) { return TokenCompareTo(a, b) == 0; } /// /// Gets the public key token hash code /// /// Public key or token /// The hash code public static int GetHashCodeToken(PublicKeyBase a) { return GetHashCode(ToPublicKeyToken(a)); } /// /// Gets the public key token hash code /// /// Public key token /// The hash code public static int GetHashCode(PublicKeyToken a) { if (a == null) return 0; return Utils.GetHashCode(a.Data); } /// /// Creates a /// /// Public key data or null /// A new instance or null if /// was null public static PublicKey CreatePublicKey(byte[] data) { if (data == null) return null; return new PublicKey(data); } /// /// Creates a /// /// Public key token data or null /// A new instance or null if /// was null public static PublicKeyToken CreatePublicKeyToken(byte[] data) { if (data == null) return null; return new PublicKeyToken(data); } /// /// Gets the raw public key / public key token byte array /// /// The instance or null /// Raw public key / public key token data or null public static byte[] GetRawData(PublicKeyBase pkb) { if (pkb == null) return null; return pkb.Data; } /// public override string ToString() { var d = Data; if (d == null || d.Length == 0) return "null"; return Utils.ToHex(d, false); } } } dnlib-2.1_VS2010/src/DotNet/PublicKeyToken.cs000066400000000000000000000016131325033663500205710ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Represents a public key token /// public sealed class PublicKeyToken : PublicKeyBase { /// /// Gets the /// public override PublicKeyToken Token { get { return this; } } /// public PublicKeyToken() : base() { } /// public PublicKeyToken(byte[] data) : base(data) { } /// public PublicKeyToken(string hexString) : base(hexString) { } /// public override bool Equals(object obj) { if ((object)this == obj) return true; var other = obj as PublicKeyToken; if (other == null) return false; return Utils.Equals(Data, other.Data); } /// public override int GetHashCode() { return Utils.GetHashCode(Data); } } } dnlib-2.1_VS2010/src/DotNet/RecursionCounter.cs000066400000000000000000000026121325033663500212120ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// Recursion counter /// public struct RecursionCounter { /// /// Max recursion count. If this is reached, we won't continue, and will use a default value. /// public const int MAX_RECURSION_COUNT = 100; int counter; /// /// Gets the recursion counter /// public int Counter { get { return counter; } } /// /// Increments if it's not too high. ALL instance methods /// that can be called recursively must call this method and /// (if this method returns true) /// /// true if it was incremented and caller can continue, false if /// it was not incremented and the caller must return to its caller. public bool Increment() { if (counter >= MAX_RECURSION_COUNT) return false; counter++; return true; } /// /// Must be called before returning to caller if /// returned true. /// public void Decrement() { #if DEBUG if (counter <= 0) throw new InvalidOperationException("recursionCounter <= 0"); #endif counter--; } /// public override string ToString() { return counter.ToString(); } } } dnlib-2.1_VS2010/src/DotNet/ReflectionExtensions.cs000066400000000000000000000077371325033663500220700ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Reflection; namespace dnlib.DotNet { /// /// Extension methods for reflection types, methods, fields /// static class ReflectionExtensions { /// /// Checks whether it's a /// /// The type public static bool IsSZArray(this Type self) { if (self == null || !self.IsArray) return false; var prop = self.GetType().GetProperty("IsSzArray", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (prop != null) return (bool)prop.GetValue(self, new object[0]); return (self.Name ?? string.Empty).EndsWith("[]"); } /// /// Gets a 's /// /// The type /// The type's element type public static ElementType GetElementType2(this Type a) { if (a == null) return ElementType.End; // Any invalid one is good enough if (a.IsArray) return IsSZArray(a) ? ElementType.SZArray : ElementType.Array; if (a.IsByRef) return ElementType.ByRef; if (a.IsPointer) return ElementType.Ptr; if (a.IsGenericParameter) return a.DeclaringMethod == null ? ElementType.Var : ElementType.MVar; if (a.IsGenericType && !a.IsGenericTypeDefinition) return ElementType.GenericInst; if (a == typeof(void)) return ElementType.Void; if (a == typeof(bool)) return ElementType.Boolean; if (a == typeof(char)) return ElementType.Char; if (a == typeof(sbyte)) return ElementType.I1; if (a == typeof(byte)) return ElementType.U1; if (a == typeof(short)) return ElementType.I2; if (a == typeof(ushort)) return ElementType.U2; if (a == typeof(int)) return ElementType.I4; if (a == typeof(uint)) return ElementType.U4; if (a == typeof(long)) return ElementType.I8; if (a == typeof(ulong)) return ElementType.U8; if (a == typeof(float)) return ElementType.R4; if (a == typeof(double)) return ElementType.R8; if (a == typeof(string)) return ElementType.String; if (a == typeof(TypedReference))return ElementType.TypedByRef; if (a == typeof(IntPtr)) return ElementType.I; if (a == typeof(UIntPtr)) return ElementType.U; if (a == typeof(object)) return ElementType.Object; return a.IsValueType ? ElementType.ValueType : ElementType.Class; } /// /// Returns true if is a generic method, but /// not a generic method definition, i.e., a MethodSpec. /// /// The method public static bool IsGenericButNotGenericMethodDefinition(this MethodBase mb) { return mb != null && !mb.IsGenericMethodDefinition && mb.IsGenericMethod; } /// /// Checks whether a parameter/prop/event type should be treated as if it is really a /// generic instance type and not a generic type definition. In the .NET metadata (method /// sig), the parameter is a generic instance type, but the CLR treats it as if it's just /// a generic type def. This seems to happen only if the parameter type is exactly the same /// type as the declaring type, eg. a method similar to: MyType<!0> MyType::SomeMethod(). /// /// Declaring type of method/event/property /// Parameter/property/event type internal static bool MustTreatTypeAsGenericInstType(this Type declaringType, Type t) { return declaringType != null && declaringType.IsGenericTypeDefinition && t == declaringType; } /// /// Checks whether is a type definition and not a type spec /// (eg. pointer or generic type instantiation) /// /// this public static bool IsTypeDef(this Type type) { return type != null && !type.HasElementType && (!type.IsGenericType || type.IsGenericTypeDefinition); } } } dnlib-2.1_VS2010/src/DotNet/ResolveException.cs000066400000000000000000000076271325033663500212120ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Runtime.Serialization; namespace dnlib.DotNet { /// /// Resolve exception base class /// [Serializable] public class ResolveException : Exception { /// /// Default constructor /// public ResolveException() { } /// /// Constructor /// /// Exception message public ResolveException(string message) : base(message) { } /// /// Constructor /// /// Exception message /// Inner exception or null if none public ResolveException(string message, Exception innerException) : base(message, innerException) { } /// /// Constructor /// /// /// protected ResolveException(SerializationInfo info, StreamingContext context) : base(info, context) { } } /// /// Thrown if an assembly couldn't be resolved /// [Serializable] public class AssemblyResolveException : ResolveException { /// /// Default constructor /// public AssemblyResolveException() { } /// /// Constructor /// /// Exception message public AssemblyResolveException(string message) : base(message) { } /// /// Constructor /// /// Exception message /// Inner exception or null if none public AssemblyResolveException(string message, Exception innerException) : base(message, innerException) { } /// /// Constructor /// /// /// protected AssemblyResolveException(SerializationInfo info, StreamingContext context) : base(info, context) { } } /// /// Thrown if a type couldn't be resolved /// [Serializable] public class TypeResolveException : ResolveException { /// /// Default constructor /// public TypeResolveException() { } /// /// Constructor /// /// Exception message public TypeResolveException(string message) : base(message) { } /// /// Constructor /// /// Exception message /// Inner exception or null if none public TypeResolveException(string message, Exception innerException) : base(message, innerException) { } /// /// Constructor /// /// /// protected TypeResolveException(SerializationInfo info, StreamingContext context) : base(info, context) { } } /// /// Thrown if a method/field couldn't be resolved /// [Serializable] public class MemberRefResolveException : ResolveException { /// /// Default constructor /// public MemberRefResolveException() { } /// /// Constructor /// /// Exception message public MemberRefResolveException(string message) : base(message) { } /// /// Constructor /// /// Exception message /// Inner exception or null if none public MemberRefResolveException(string message, Exception innerException) : base(message, innerException) { } /// /// Constructor /// /// /// protected MemberRefResolveException(SerializationInfo info, StreamingContext context) : base(info, context) { } } } dnlib-2.1_VS2010/src/DotNet/Resolver.cs000066400000000000000000000123111325033663500174770ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using dnlib.Threading; namespace dnlib.DotNet { /// /// Resolves types, methods, fields /// public sealed class Resolver : IResolver { readonly IAssemblyResolver assemblyResolver; /// /// true to project WinMD types to CLR types, eg. Windows.UI.Xaml.Interop.TypeName /// gets converted to System.Type before trying to resolve the type. This is enabled /// by default. /// public bool ProjectWinMDRefs { get { return projectWinMDRefs; } set { projectWinMDRefs = value; } } bool projectWinMDRefs = true; /// /// Constructor /// /// The assembly resolver public Resolver(IAssemblyResolver assemblyResolver) { if (assemblyResolver == null) throw new ArgumentNullException("assemblyResolver"); this.assemblyResolver = assemblyResolver; } /// public TypeDef Resolve(TypeRef typeRef, ModuleDef sourceModule) { if (typeRef == null) return null; if (ProjectWinMDRefs) typeRef = WinMDHelpers.ToCLR(typeRef.Module ?? sourceModule, typeRef) ?? typeRef; var nonNestedTypeRef = TypeRef.GetNonNestedTypeRef(typeRef); if (nonNestedTypeRef == null) return null; var nonNestedResolutionScope = nonNestedTypeRef.ResolutionScope; var nonNestedModule = nonNestedTypeRef.Module; var asmRef = nonNestedResolutionScope as AssemblyRef; if (asmRef != null) { var asm = assemblyResolver.Resolve(asmRef, sourceModule ?? nonNestedModule); return asm == null ? null : asm.Find(typeRef) ?? ResolveExportedType(asm.Modules, typeRef, sourceModule); } var moduleDef = nonNestedResolutionScope as ModuleDef; if (moduleDef != null) return moduleDef.Find(typeRef) ?? ResolveExportedType(new ModuleDef[] { moduleDef }, typeRef, sourceModule); var moduleRef = nonNestedResolutionScope as ModuleRef; if (moduleRef != null) { if (nonNestedModule == null) return null; if (new SigComparer().Equals(moduleRef, nonNestedModule)) return nonNestedModule.Find(typeRef) ?? ResolveExportedType(new ModuleDef[] { nonNestedModule }, typeRef, sourceModule); var nonNestedAssembly = nonNestedModule.Assembly; if (nonNestedAssembly == null) return null; var resolvedModule = nonNestedAssembly.FindModule(moduleRef.Name); return resolvedModule == null ? null : resolvedModule.Find(typeRef) ?? ResolveExportedType(new ModuleDef[] { resolvedModule }, typeRef, sourceModule); } return null; } TypeDef ResolveExportedType(IList modules, TypeRef typeRef, ModuleDef sourceModule) { for (int i = 0; i < 30; i++) { var exportedType = FindExportedType(modules, typeRef); if (exportedType == null) return null; var asmResolver = modules[0].Context.AssemblyResolver; var etAsm = asmResolver.Resolve(exportedType.DefinitionAssembly, sourceModule ?? typeRef.Module); if (etAsm == null) return null; var td = etAsm.Find(typeRef); if (td != null) return td; modules = etAsm.Modules; } return null; } static ExportedType FindExportedType(IList modules, TypeRef typeRef) { if (typeRef == null) return null; foreach (var module in modules.GetSafeEnumerable()) { foreach (var exportedType in module.ExportedTypes.GetSafeEnumerable()) { if (new SigComparer(SigComparerOptions.DontCompareTypeScope).Equals(exportedType, typeRef)) return exportedType; } } return null; } /// public IMemberForwarded Resolve(MemberRef memberRef) { if (memberRef == null) return null; if (ProjectWinMDRefs) memberRef = WinMDHelpers.ToCLR(memberRef.Module, memberRef) ?? memberRef; var parent = memberRef.Class; var method = parent as MethodDef; if (method != null) return method; var declaringType = GetDeclaringType(memberRef, parent); return declaringType == null ? null : declaringType.Resolve(memberRef); } TypeDef GetDeclaringType(MemberRef memberRef, IMemberRefParent parent) { if (memberRef == null || parent == null) return null; var ts = parent as TypeSpec; if (ts != null) parent = ts.ScopeType; var declaringTypeDef = parent as TypeDef; if (declaringTypeDef != null) return declaringTypeDef; var declaringTypeRef = parent as TypeRef; if (declaringTypeRef != null) return Resolve(declaringTypeRef, memberRef.Module); // A module ref is used to reference the global type of a module in the same // assembly as the current module. var moduleRef = parent as ModuleRef; if (moduleRef != null) { var module = memberRef.Module; if (module == null) return null; TypeDef globalType = null; if (new SigComparer().Equals(module, moduleRef)) globalType = module.GlobalType; var modAsm = module.Assembly; if (globalType == null && modAsm != null) { var moduleDef = modAsm.FindModule(moduleRef.Name); if (moduleDef != null) globalType = moduleDef.GlobalType; } return globalType; } var method = parent as MethodDef; if (method != null) return method.DeclaringType; return null; } } } dnlib-2.1_VS2010/src/DotNet/Resource.cs000066400000000000000000000217741325033663500175020ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using dnlib.IO; using dnlib.DotNet.MD; using dnlib.Threading; namespace dnlib.DotNet { /// /// Type of resource /// public enum ResourceType { /// /// It's a /// Embedded, /// /// It's a /// AssemblyLinked, /// /// It's a /// Linked, } /// /// Resource base class /// public abstract class Resource : IDisposable, IMDTokenProvider { uint rid; uint? offset; UTF8String name; ManifestResourceAttributes flags; /// public MDToken MDToken { get { return new MDToken(Table.ManifestResource, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// /// Gets/sets the offset of the resource /// public uint? Offset { get { return offset; } set { offset = value; } } /// /// Gets/sets the name /// public UTF8String Name { get { return name; } set { name = value; } } /// /// Gets/sets the flags /// public ManifestResourceAttributes Attributes { get { return flags; } set { flags = value; } } /// /// Gets the type of resource /// public abstract ResourceType ResourceType { get; } /// /// Gets/sets the visibility /// public ManifestResourceAttributes Visibility { get { return flags & ManifestResourceAttributes.VisibilityMask; } set { flags = (flags & ~ManifestResourceAttributes.VisibilityMask) | (value & ManifestResourceAttributes.VisibilityMask); } } /// /// true if is set /// public bool IsPublic { get { return (flags & ManifestResourceAttributes.VisibilityMask) == ManifestResourceAttributes.Public; } } /// /// true if is set /// public bool IsPrivate { get { return (flags & ManifestResourceAttributes.VisibilityMask) == ManifestResourceAttributes.Private; } } /// /// Constructor /// /// Name /// flags protected Resource(UTF8String name, ManifestResourceAttributes flags) { this.name = name; this.flags = flags; } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose method /// /// true if called by protected virtual void Dispose(bool disposing) { } } /// /// A resource that is embedded in a .NET module. This is the most common type of resource. /// public sealed class EmbeddedResource : Resource { IImageStream dataStream; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// public override ResourceType ResourceType { get { return ResourceType.Embedded; } } /// /// Gets/sets the resource data. It's never null. /// public IImageStream Data { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return dataStream; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } set { if (value == null) throw new ArgumentNullException("value"); #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (value == dataStream) return; if (dataStream != null) dataStream.Dispose(); dataStream = value; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Constructor /// /// Name of resource /// Resource data public EmbeddedResource(UTF8String name, byte[] data) : this(name, data, ManifestResourceAttributes.Private) { } /// /// Constructor /// /// Name of resource /// Resource data /// Resource flags public EmbeddedResource(UTF8String name, byte[] data, ManifestResourceAttributes flags) : this(name, new MemoryImageStream(0, data, 0, data.Length), flags) { } /// /// Constructor /// /// Name of resource /// Resource data public EmbeddedResource(UTF8String name, IImageStream dataStream) : this(name, dataStream, ManifestResourceAttributes.Private) { } /// /// Constructor /// /// Name of resource /// Resource data /// Resource flags public EmbeddedResource(UTF8String name, IImageStream dataStream, ManifestResourceAttributes flags) : base(name, flags) { if (dataStream == null) throw new ArgumentNullException("dataStream"); this.dataStream = dataStream; } /// /// Creates a new resource stream that can access the same data as the original /// Stream. Note that the data is shared between these streams. /// /// A new instance public IImageStream GetClonedResourceStream() { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return dataStream.Clone(); #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } /// /// Gets the resource data as a /// /// A stream public Stream GetResourceStream() { return GetClonedResourceStream().CreateStream(true); } /// /// Gets the resource data as a byte array /// /// The resource data public byte[] GetResourceData() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif return dataStream.ReadAllBytes(); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// protected override void Dispose(bool disposing) { if (!disposing) return; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (dataStream != null) dataStream.Dispose(); dataStream = null; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif base.Dispose(disposing); } /// public override string ToString() { var ds = dataStream; return string.Format("{0} - size: {1}", UTF8String.ToSystemStringOrEmpty(Name), ds == null ? 0 : ds.Length); } } /// /// A reference to a resource in another assembly /// public sealed class AssemblyLinkedResource : Resource { AssemblyRef asmRef; /// public override ResourceType ResourceType { get { return ResourceType.AssemblyLinked; } } /// /// Gets/sets the assembly reference /// public AssemblyRef Assembly { get { return asmRef; } set { if (value == null) throw new ArgumentNullException("value"); asmRef = value; } } /// /// Constructor /// /// Name of resource /// Assembly reference /// Resource flags public AssemblyLinkedResource(UTF8String name, AssemblyRef asmRef, ManifestResourceAttributes flags) : base(name, flags) { if (asmRef == null) throw new ArgumentNullException("asmRef"); this.asmRef = asmRef; } /// public override string ToString() { return string.Format("{0} - assembly: {1}", UTF8String.ToSystemStringOrEmpty(Name), asmRef.FullName); } } /// /// A resource that is stored in a file on disk /// public sealed class LinkedResource : Resource { FileDef file; /// public override ResourceType ResourceType { get { return ResourceType.Linked; } } /// /// Gets/sets the file /// public FileDef File { get { return file; } set { if (value == null) throw new ArgumentNullException("value"); file = value; } } /// /// Gets/sets the hash /// public byte[] Hash { get { return file.HashValue; } set { file.HashValue = value; } } /// /// Gets/sets the file name /// public UTF8String FileName { get { return file == null ? UTF8String.Empty : file.Name; } } /// /// Constructor /// /// Name of resource /// The file /// Resource flags public LinkedResource(UTF8String name, FileDef file, ManifestResourceAttributes flags) : base(name, flags) { this.file = file; } /// public override string ToString() { return string.Format("{0} - file: {1}", UTF8String.ToSystemStringOrEmpty(Name), UTF8String.ToSystemStringOrEmpty(FileName)); } } } dnlib-2.1_VS2010/src/DotNet/ResourceCollection.cs000066400000000000000000000114741325033663500215120ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.Utils; using dnlib.Threading; namespace dnlib.DotNet { /// /// A collection of s /// public class ResourceCollection : LazyList { /// /// Default constructor /// public ResourceCollection() { } /// /// Constructor /// /// List listener public ResourceCollection(IListListener listener) : base(listener) { } /// /// Constructor /// /// Initial length of the list /// Context passed to /// Delegate instance that returns original values public ResourceCollection(int length, object context, MFunc readOriginalValue) : base(length, context, readOriginalValue) { } /// /// Finds the index of a resource /// /// Name of resource /// The index of the or -1 if none was found public int IndexOf(UTF8String name) { int i = -1; foreach (var resource in this.GetSafeEnumerable()) { i++; if (resource != null && resource.Name == name) return i; } return -1; } /// /// Finds the index of an embedded resource /// /// Name of resource /// The index of the or -1 if none was found public int IndexOfEmbeddedResource(UTF8String name) { int i = -1; foreach (var resource in this.GetSafeEnumerable()) { i++; if (resource != null && resource.ResourceType == ResourceType.Embedded && resource.Name == name) return i; } return -1; } /// /// Finds the index of an assembly linked resource /// /// Name of resource /// The index of the or -1 if none was found public int IndexOfAssemblyLinkedResource(UTF8String name) { int i = -1; foreach (var resource in this.GetSafeEnumerable()) { i++; if (resource != null && resource.ResourceType == ResourceType.AssemblyLinked && resource.Name == name) return i; } return -1; } /// /// Finds the index of a linked resource /// /// Name of resource /// The index of the or -1 if none was found public int IndexOfLinkedResource(UTF8String name) { int i = -1; foreach (var resource in this.GetSafeEnumerable()) { i++; if (resource != null && resource.ResourceType == ResourceType.Linked && resource.Name == name) return i; } return -1; } /// /// Finds a resource /// /// Name of resource /// The or null if none was found public Resource Find(UTF8String name) { foreach (var resource in this.GetSafeEnumerable()) { if (resource != null && resource.Name == name) return resource; } return null; } /// /// Finds an embedded resource /// /// Name of resource /// The or null if none was found public EmbeddedResource FindEmbeddedResource(UTF8String name) { foreach (var resource in this.GetSafeEnumerable()) { if (resource != null && resource.ResourceType == ResourceType.Embedded && resource.Name == name) return (EmbeddedResource)resource; } return null; } /// /// Finds an assembly linked resource /// /// Name of resource /// The or null if none was found public AssemblyLinkedResource FindAssemblyLinkedResource(UTF8String name) { foreach (var resource in this.GetSafeEnumerable()) { if (resource != null && resource.ResourceType == ResourceType.AssemblyLinked && resource.Name == name) return (AssemblyLinkedResource)resource; } return null; } /// /// Finds a linked resource /// /// Name of resource /// The or null if none was found public LinkedResource FindLinkedResource(UTF8String name) { foreach (var resource in this.GetSafeEnumerable()) { if (resource != null && resource.ResourceType == ResourceType.Linked && resource.Name == name) return (LinkedResource)resource; } return null; } } } dnlib-2.1_VS2010/src/DotNet/Resources/000077500000000000000000000000001325033663500173235ustar00rootroot00000000000000dnlib-2.1_VS2010/src/DotNet/Resources/BuiltInResourceData.cs000066400000000000000000000070001325033663500235170ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using System.Runtime.Serialization; using dnlib.IO; namespace dnlib.DotNet.Resources { /// /// Built-in resource data /// public sealed class BuiltInResourceData : IResourceData { readonly ResourceTypeCode code; readonly object data; /// /// Gets the data /// public object Data { get { return data; } } /// public ResourceTypeCode Code { get { return code; } } /// public FileOffset StartOffset { get; set; } /// public FileOffset EndOffset { get; set; } /// /// Constructor /// /// Type of data /// Data public BuiltInResourceData(ResourceTypeCode code, object data) { this.code = code; this.data = data; } /// public void WriteData(BinaryWriter writer, IFormatter formatter) { switch (code) { case ResourceTypeCode.Null: break; case ResourceTypeCode.String: writer.Write((string)data); break; case ResourceTypeCode.Boolean: writer.Write((bool)data); break; case ResourceTypeCode.Char: writer.Write((ushort)(char)data); break; case ResourceTypeCode.Byte: writer.Write((byte)data); break; case ResourceTypeCode.SByte: writer.Write((sbyte)data); break; case ResourceTypeCode.Int16: writer.Write((short)data); break; case ResourceTypeCode.UInt16: writer.Write((ushort)data); break; case ResourceTypeCode.Int32: writer.Write((int)data); break; case ResourceTypeCode.UInt32: writer.Write((uint)data); break; case ResourceTypeCode.Int64: writer.Write((long)data); break; case ResourceTypeCode.UInt64: writer.Write((ulong)data); break; case ResourceTypeCode.Single: writer.Write((float)data); break; case ResourceTypeCode.Double: writer.Write((double)data); break; case ResourceTypeCode.Decimal: writer.Write((decimal)data); break; case ResourceTypeCode.DateTime: writer.Write(((DateTime)data).ToBinary()); break; case ResourceTypeCode.TimeSpan: writer.Write(((TimeSpan)data).Ticks); break; case ResourceTypeCode.ByteArray: case ResourceTypeCode.Stream: var ary = (byte[])data; writer.Write(ary.Length); writer.Write(ary); break; default: throw new InvalidOperationException("Unknown resource type code"); } } /// public override string ToString() { switch (code) { case ResourceTypeCode.Null: return "null"; case ResourceTypeCode.String: case ResourceTypeCode.Boolean: case ResourceTypeCode.Char: case ResourceTypeCode.Byte: case ResourceTypeCode.SByte: case ResourceTypeCode.Int16: case ResourceTypeCode.UInt16: case ResourceTypeCode.Int32: case ResourceTypeCode.UInt32: case ResourceTypeCode.Int64: case ResourceTypeCode.UInt64: case ResourceTypeCode.Single: case ResourceTypeCode.Double: case ResourceTypeCode.Decimal: case ResourceTypeCode.DateTime: case ResourceTypeCode.TimeSpan: return string.Format("{0}: '{1}'", code, data); case ResourceTypeCode.ByteArray: case ResourceTypeCode.Stream: var ary = data as byte[]; if (ary != null) return string.Format("{0}: Length: {1}", code, ary.Length); return string.Format("{0}: '{1}'", code, data); default: return string.Format("{0}: '{1}'", code, data); } } } } dnlib-2.1_VS2010/src/DotNet/Resources/IResourceData.cs000066400000000000000000000016141325033663500223460ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using System.Runtime.Serialization; using dnlib.IO; namespace dnlib.DotNet.Resources { /// /// Implemented by all resource data /// public interface IResourceData : IFileSection { /// /// Gets the type of data /// ResourceTypeCode Code { get; } /// /// Start offset of the section in the file /// new FileOffset StartOffset { get; set; } /// /// End offset of the section in the file. This is one byte after the last /// valid offset in the section. /// new FileOffset EndOffset { get; set; } /// /// Writes the data /// /// Writer /// Formatter if needed by implementer void WriteData(BinaryWriter writer, IFormatter formatter); } } dnlib-2.1_VS2010/src/DotNet/Resources/ResourceDataCreator.cs000066400000000000000000000246671325033663500235720ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; namespace dnlib.DotNet.Resources { /// /// Creates resource data /// public class ResourceDataCreator { readonly ModuleDef module; readonly ModuleDefMD moduleMD; readonly Dictionary dict = new Dictionary(StringComparer.Ordinal); readonly Dictionary asmNameToAsmFullName = new Dictionary(StringComparer.Ordinal); /// /// Gets the owner module /// protected ModuleDef Module { get { return module; } } /// /// Constructor /// /// Owner module public ResourceDataCreator(ModuleDef module) { this.module = module; this.moduleMD = module as ModuleDefMD; } /// /// Gets number of user data types /// public int Count { get { return dict.Count; } } /// /// Create null data /// /// public BuiltInResourceData CreateNull() { return new BuiltInResourceData(ResourceTypeCode.Null, null); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(string value) { return new BuiltInResourceData(ResourceTypeCode.String, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(bool value) { return new BuiltInResourceData(ResourceTypeCode.Boolean, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(char value) { return new BuiltInResourceData(ResourceTypeCode.Char, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(byte value) { return new BuiltInResourceData(ResourceTypeCode.Byte, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(sbyte value) { return new BuiltInResourceData(ResourceTypeCode.SByte, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(short value) { return new BuiltInResourceData(ResourceTypeCode.Int16, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(ushort value) { return new BuiltInResourceData(ResourceTypeCode.UInt16, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(int value) { return new BuiltInResourceData(ResourceTypeCode.Int32, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(uint value) { return new BuiltInResourceData(ResourceTypeCode.UInt32, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(long value) { return new BuiltInResourceData(ResourceTypeCode.Int64, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(ulong value) { return new BuiltInResourceData(ResourceTypeCode.UInt64, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(float value) { return new BuiltInResourceData(ResourceTypeCode.Single, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(double value) { return new BuiltInResourceData(ResourceTypeCode.Double, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(decimal value) { return new BuiltInResourceData(ResourceTypeCode.Decimal, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(DateTime value) { return new BuiltInResourceData(ResourceTypeCode.DateTime, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData Create(TimeSpan value) { return new BuiltInResourceData(ResourceTypeCode.TimeSpan, value); } /// /// Creates array data /// /// Value /// public BuiltInResourceData Create(byte[] value) { return new BuiltInResourceData(ResourceTypeCode.ByteArray, value); } /// /// Creates data /// /// Value /// public BuiltInResourceData CreateStream(byte[] value) { return new BuiltInResourceData(ResourceTypeCode.Stream, value); } /// /// Creates serialized data /// /// Serialized data /// Type of serialized data /// public BinaryResourceData CreateSerialized(byte[] value, UserResourceType type) { return new BinaryResourceData(CreateUserResourceType(type.Name, true), value); } /// /// Creates serialized data /// /// Serialized data /// public BinaryResourceData CreateSerialized(byte[] value) { string assemblyName, typeName; if (!GetSerializedTypeAndAssemblyName(value, out assemblyName, out typeName)) throw new ApplicationException("Could not get serialized type name"); string fullName = string.Format("{0}, {1}", typeName, assemblyName); return new BinaryResourceData(CreateUserResourceType(fullName), value); } sealed class MyBinder : SerializationBinder { public class OkException : Exception { public string AssemblyName { get; set; } public string TypeName { get; set; } } public override Type BindToType(string assemblyName, string typeName) { throw new OkException { AssemblyName = assemblyName, TypeName = typeName, }; } } bool GetSerializedTypeAndAssemblyName(byte[] value, out string assemblyName, out string typeName) { try { var formatter = new BinaryFormatter(); formatter.Binder = new MyBinder(); formatter.Deserialize(new MemoryStream(value)); } catch (MyBinder.OkException ex) { assemblyName = ex.AssemblyName; typeName = ex.TypeName; return true; } catch { } assemblyName = null; typeName = null; return false; } /// /// Creates a user type. If the type already exists, the existing value is returned. /// /// Full name of type /// public UserResourceType CreateUserResourceType(string fullName) { return CreateUserResourceType(fullName, false); } /// /// Creates a user type. If the type already exists, the existing value is returned. /// /// Full name of type /// Use without converting it to a /// type in an existing assembly reference /// UserResourceType CreateUserResourceType(string fullName, bool useFullName) { UserResourceType type; if (dict.TryGetValue(fullName, out type)) return type; var newFullName = useFullName ? fullName : GetRealTypeFullName(fullName); type = new UserResourceType(newFullName, ResourceTypeCode.UserTypes + dict.Count); dict[fullName] = type; dict[newFullName] = type; return type; } string GetRealTypeFullName(string fullName) { var tr = TypeNameParser.ParseReflection(module, fullName, null); if (tr == null) return fullName; var asmRef = tr.DefinitionAssembly; if (asmRef == null) return fullName; var newFullName = fullName; string assemblyName = GetRealAssemblyName(asmRef); if (!string.IsNullOrEmpty(assemblyName)) newFullName = string.Format("{0}, {1}", tr.ReflectionFullName, assemblyName); return newFullName; } string GetRealAssemblyName(IAssembly asm) { string assemblyName = asm.FullName; string newAsmName; if (!asmNameToAsmFullName.TryGetValue(assemblyName, out newAsmName)) asmNameToAsmFullName[assemblyName] = newAsmName = TryGetRealAssemblyName(asm); return newAsmName; } string TryGetRealAssemblyName(IAssembly asm) { var simpleName = asm.Name; if (simpleName == module.CorLibTypes.AssemblyRef.Name) return module.CorLibTypes.AssemblyRef.FullName; if (moduleMD != null) { var asmRef = moduleMD.GetAssemblyRef(simpleName); if (asmRef != null) return asmRef.FullName; } return GetAssemblyFullName(simpleName); } /// /// Converts an assembly simple name (eg. mscorlib) to the full name of the assembly, /// which includes the version, public key token, etc. Returns null if it's /// unknown. /// /// Simple name of assembly /// protected virtual string GetAssemblyFullName(string simpleName) { return null; } /// /// Gets all types sorted by /// /// public List GetSortedTypes() { var list = new List(dict.Values); list.Sort((a, b) => ((int)a.Code).CompareTo((int)b.Code)); return list; } } } dnlib-2.1_VS2010/src/DotNet/Resources/ResourceElement.cs000066400000000000000000000007641325033663500227620ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Resources { /// /// Resource element /// public sealed class ResourceElement { /// /// Name of resource /// public string Name { get; set; } /// /// Data of resource /// public IResourceData ResourceData { get; set; } /// public override string ToString() { return string.Format("N: {0}, V: {1}", Name, ResourceData); } } } dnlib-2.1_VS2010/src/DotNet/Resources/ResourceElementSet.cs000066400000000000000000000015311325033663500234270ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; namespace dnlib.DotNet.Resources { /// /// Resource element set /// public sealed class ResourceElementSet { readonly Dictionary dict = new Dictionary(StringComparer.Ordinal); /// /// Gets the number of elements in the set /// public int Count { get { return dict.Count; } } /// /// Gets all resource elements /// public IEnumerable ResourceElements { get { return dict.Values; } } /// /// Adds a new resource to the set, overwriting any existing resource /// /// public void Add(ResourceElement elem) { dict[elem.Name] = elem; } } } dnlib-2.1_VS2010/src/DotNet/Resources/ResourceReader.cs000066400000000000000000000222311325033663500225640ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.Text; using System.Text.RegularExpressions; using dnlib.IO; namespace dnlib.DotNet.Resources { /// /// Thrown by /// [Serializable] public sealed class ResourceReaderException : Exception { /// /// Constructor /// public ResourceReaderException() { } /// /// Constructor /// /// Message public ResourceReaderException(string msg) : base(msg) { } /// /// Constructor /// /// /// public ResourceReaderException(SerializationInfo info, StreamingContext context) : base(info, context) { } } /// /// Gets called to create a from serialized data. Returns null /// if a default instance should be created. /// /// ResourceDataCreator /// Serialized type /// Serialized data /// public delegate IResourceData CreateResourceDataDelegate(ResourceDataCreator resourceDataCreator, UserResourceType type, byte[] serializedData); /// /// Reads .NET resources /// public struct ResourceReader { readonly IBinaryReader reader; readonly long baseFileOffset; readonly ResourceDataCreator resourceDataCreator; readonly CreateResourceDataDelegate createResourceDataDelegate; ResourceReader(ModuleDef module, IBinaryReader reader, CreateResourceDataDelegate createResourceDataDelegate) { this.reader = reader; this.resourceDataCreator = new ResourceDataCreator(module); this.createResourceDataDelegate = createResourceDataDelegate; var stream = reader as IImageStream; this.baseFileOffset = stream == null ? 0 : (long)stream.FileOffset; } /// /// Returns true if it's possibly resources file data /// /// Reader /// public static bool CouldBeResourcesFile(IBinaryReader reader) { return reader.CanRead(4) && reader.ReadUInt32() == 0xBEEFCACE; } /// /// Reads a .NET resource /// /// Owner module /// Data of resource /// public static ResourceElementSet Read(ModuleDef module, IBinaryReader reader) { return Read(module, reader, null); } /// /// Reads a .NET resource /// /// Owner module /// Data of resource /// Call back that gets called to create a instance. Can be null. /// public static ResourceElementSet Read(ModuleDef module, IBinaryReader reader, CreateResourceDataDelegate createResourceDataDelegate) { return new ResourceReader(module, reader, createResourceDataDelegate).Read(); } ResourceElementSet Read() { ResourceElementSet resources = new ResourceElementSet(); uint sig = reader.ReadUInt32(); if (sig != 0xBEEFCACE) throw new ResourceReaderException(string.Format("Invalid resource sig: {0:X8}", sig)); if (!CheckReaders()) throw new ResourceReaderException("Invalid resource reader"); int version = reader.ReadInt32(); if (version != 2)//TODO: Support version 1 throw new ResourceReaderException(string.Format("Invalid resource version: {0}", version)); int numResources = reader.ReadInt32(); if (numResources < 0) throw new ResourceReaderException(string.Format("Invalid number of resources: {0}", numResources)); int numUserTypes = reader.ReadInt32(); if (numUserTypes < 0) throw new ResourceReaderException(string.Format("Invalid number of user types: {0}", numUserTypes)); var userTypes = new List(); for (int i = 0; i < numUserTypes; i++) userTypes.Add(new UserResourceType(reader.ReadString(), ResourceTypeCode.UserTypes + i)); reader.Position = (reader.Position + 7) & ~7; var hashes = new int[numResources]; for (int i = 0; i < numResources; i++) hashes[i] = reader.ReadInt32(); var offsets = new int[numResources]; for (int i = 0; i < numResources; i++) offsets[i] = reader.ReadInt32(); long baseOffset = reader.Position; long dataBaseOffset = reader.ReadInt32(); long nameBaseOffset = reader.Position; long end = reader.Length; var infos = new List(numResources); for (int i = 0; i < numResources; i++) { reader.Position = nameBaseOffset + offsets[i]; var name = reader.ReadString(Encoding.Unicode); long offset = dataBaseOffset + reader.ReadInt32(); infos.Add(new ResourceInfo(name, offset)); } infos.Sort((a, b) => a.offset.CompareTo(b.offset)); for (int i = 0; i < infos.Count; i++) { var info = infos[i]; var element = new ResourceElement(); element.Name = info.name; reader.Position = info.offset; long nextDataOffset = i == infos.Count - 1 ? end : infos[i + 1].offset; int size = (int)(nextDataOffset - info.offset); element.ResourceData = ReadResourceData(userTypes, size); element.ResourceData.StartOffset = this.baseFileOffset + (FileOffset)info.offset; element.ResourceData.EndOffset = this.baseFileOffset + (FileOffset)reader.Position; resources.Add(element); } return resources; } sealed class ResourceInfo { public string name; public long offset; public ResourceInfo(string name, long offset) { this.name = name; this.offset = offset; } public override string ToString() { return string.Format("{0:X8} - {1}", offset, name); } } IResourceData ReadResourceData(List userTypes, int size) { uint code = ReadUInt32(reader); switch ((ResourceTypeCode)code) { case ResourceTypeCode.Null: return resourceDataCreator.CreateNull(); case ResourceTypeCode.String: return resourceDataCreator.Create(reader.ReadString()); case ResourceTypeCode.Boolean: return resourceDataCreator.Create(reader.ReadBoolean()); case ResourceTypeCode.Char: return resourceDataCreator.Create((char)reader.ReadUInt16()); case ResourceTypeCode.Byte: return resourceDataCreator.Create(reader.ReadByte()); case ResourceTypeCode.SByte: return resourceDataCreator.Create(reader.ReadSByte()); case ResourceTypeCode.Int16: return resourceDataCreator.Create(reader.ReadInt16()); case ResourceTypeCode.UInt16: return resourceDataCreator.Create(reader.ReadUInt16()); case ResourceTypeCode.Int32: return resourceDataCreator.Create(reader.ReadInt32()); case ResourceTypeCode.UInt32: return resourceDataCreator.Create(reader.ReadUInt32()); case ResourceTypeCode.Int64: return resourceDataCreator.Create(reader.ReadInt64()); case ResourceTypeCode.UInt64: return resourceDataCreator.Create(reader.ReadUInt64()); case ResourceTypeCode.Single: return resourceDataCreator.Create(reader.ReadSingle()); case ResourceTypeCode.Double: return resourceDataCreator.Create(reader.ReadDouble()); case ResourceTypeCode.Decimal: return resourceDataCreator.Create(reader.ReadDecimal()); case ResourceTypeCode.DateTime: return resourceDataCreator.Create(DateTime.FromBinary(reader.ReadInt64())); case ResourceTypeCode.TimeSpan: return resourceDataCreator.Create(new TimeSpan(reader.ReadInt64())); case ResourceTypeCode.ByteArray:return resourceDataCreator.Create(reader.ReadBytes(reader.ReadInt32())); case ResourceTypeCode.Stream: return resourceDataCreator.CreateStream(reader.ReadBytes(reader.ReadInt32())); default: int userTypeIndex = (int)(code - (uint)ResourceTypeCode.UserTypes); if (userTypeIndex < 0 || userTypeIndex >= userTypes.Count) throw new ResourceReaderException(string.Format("Invalid resource data code: {0}", code)); var userType = userTypes[userTypeIndex]; var serializedData = reader.ReadBytes(size); if (createResourceDataDelegate != null) { var res = createResourceDataDelegate(resourceDataCreator, userType, serializedData); if (res != null) return res; } return resourceDataCreator.CreateSerialized(serializedData, userType); } } static uint ReadUInt32(IBinaryReader reader) { try { return reader.Read7BitEncodedUInt32(); } catch { throw new ResourceReaderException("Invalid encoded int32"); } } bool CheckReaders() { bool validReader = false; int numReaders = reader.ReadInt32(); if (numReaders < 0) throw new ResourceReaderException(string.Format("Invalid number of readers: {0}", numReaders)); int readersSize = reader.ReadInt32(); if (readersSize < 0) throw new ResourceReaderException(string.Format("Invalid readers size: {0:X8}", readersSize)); for (int i = 0; i < numReaders; i++) { var resourceReaderFullName = reader.ReadString(); /*var resourceSetFullName = */reader.ReadString(); if (Regex.IsMatch(resourceReaderFullName, @"^System\.Resources\.ResourceReader,\s*mscorlib,")) validReader = true; } return validReader; } } } dnlib-2.1_VS2010/src/DotNet/Resources/ResourceTypeCode.cs000066400000000000000000000032331325033663500230770ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Resources { /// /// Type of resource /// public enum ResourceTypeCode { /// /// null /// Null = 0, /// /// /// String = 1, /// /// /// Boolean = 2, /// /// /// Char = 3, /// /// /// Byte = 4, /// /// /// SByte = 5, /// /// /// Int16 = 6, /// /// /// UInt16 = 7, /// /// /// Int32 = 8, /// /// /// UInt32 = 9, /// /// /// Int64 = 0x0A, /// /// /// UInt64 = 0x0B, /// /// /// Single = 0x0C, /// /// /// Double = 0x0D, /// /// /// Decimal = 0x0E, /// /// /// DateTime = 0x0F, /// /// /// TimeSpan = 0x10, /// /// array /// ByteArray = 0x20, /// /// /// Stream = 0x21, /// /// Start of user types /// UserTypes = 0x40, } } dnlib-2.1_VS2010/src/DotNet/Resources/ResourceWriter.cs000066400000000000000000000105561325033663500226450ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Text; namespace dnlib.DotNet.Resources { /// /// Writes .NET resources /// public sealed class ResourceWriter { ModuleDef module; BinaryWriter writer; ResourceElementSet resources; ResourceDataCreator typeCreator; Dictionary dataToNewType = new Dictionary(); ResourceWriter(ModuleDef module, Stream stream, ResourceElementSet resources) { this.module = module; this.typeCreator = new ResourceDataCreator(module); this.writer = new BinaryWriter(stream); this.resources = resources; } /// /// Write .NET resources /// /// Owner module /// Output stream /// .NET resources public static void Write(ModuleDef module, Stream stream, ResourceElementSet resources) { new ResourceWriter(module, stream, resources).Write(); } void Write() { InitializeUserTypes(); writer.Write(0xBEEFCACE); writer.Write(1); WriteReaderType(); writer.Write(2);//TODO: Support version 1 writer.Write(resources.Count); writer.Write(typeCreator.Count); foreach (var userType in typeCreator.GetSortedTypes()) writer.Write(userType.Name); int extraBytes = 8 - ((int)writer.BaseStream.Position & 7); if (extraBytes != 8) { for (int i = 0; i < extraBytes; i++) writer.Write((byte)'X'); } var nameOffsetStream = new MemoryStream(); var nameOffsetWriter = new BinaryWriter(nameOffsetStream, Encoding.Unicode); var dataStream = new MemoryStream(); var dataWriter = new BinaryWriter(dataStream); var hashes = new int[resources.Count]; var offsets = new int[resources.Count]; var formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File | StreamingContextStates.Persistence)); int index = 0; foreach (var info in resources.ResourceElements) { offsets[index] = (int)nameOffsetWriter.BaseStream.Position; hashes[index] = (int)Hash(info.Name); index++; nameOffsetWriter.Write(info.Name); nameOffsetWriter.Write((int)dataWriter.BaseStream.Position); WriteData(dataWriter, info, formatter); } Array.Sort(hashes, offsets); foreach (var hash in hashes) writer.Write(hash); foreach (var offset in offsets) writer.Write(offset); writer.Write((int)writer.BaseStream.Position + (int)nameOffsetStream.Length + 4); writer.Write(nameOffsetStream.ToArray()); writer.Write(dataStream.ToArray()); } void WriteData(BinaryWriter writer, ResourceElement info, IFormatter formatter) { var code = GetResourceType(info.ResourceData); WriteUInt32(writer, (uint)code); info.ResourceData.WriteData(writer, formatter); } static void WriteUInt32(BinaryWriter writer, uint value) { while (value >= 0x80) { writer.Write((byte)(value | 0x80)); value >>= 7; } writer.Write((byte)value); } ResourceTypeCode GetResourceType(IResourceData data) { if (data is BuiltInResourceData) return data.Code; var userData = (UserResourceData)data; return dataToNewType[userData].Code; } static uint Hash(string key) { uint val = 0x1505; foreach (var c in key) val = ((val << 5) + val) ^ (uint)c; return val; } void InitializeUserTypes() { foreach (var resource in resources.ResourceElements) { var data = resource.ResourceData as UserResourceData; if (data == null) continue; var newType = typeCreator.CreateUserResourceType(data.TypeName); dataToNewType[data] = newType; } } void WriteReaderType() { var memStream = new MemoryStream(); var headerWriter = new BinaryWriter(memStream); var mscorlibFullName = GetMscorlibFullname(); headerWriter.Write("System.Resources.ResourceReader, " + mscorlibFullName); headerWriter.Write("System.Resources.RuntimeResourceSet"); writer.Write((int)memStream.Position); writer.Write(memStream.ToArray()); } string GetMscorlibFullname() { if (module.CorLibTypes.AssemblyRef.Name == "mscorlib") return module.CorLibTypes.AssemblyRef.FullName; return "mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; } } } dnlib-2.1_VS2010/src/DotNet/Resources/UserResourceData.cs000066400000000000000000000033011325033663500230670ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using System.Runtime.Serialization; using dnlib.IO; namespace dnlib.DotNet.Resources { /// /// Base class of all user data /// public abstract class UserResourceData : IResourceData { readonly UserResourceType type; /// /// Full name including assembly of type /// public string TypeName { get { return type.Name; } } /// /// User type code /// public ResourceTypeCode Code { get { return type.Code; } } /// public FileOffset StartOffset { get; set; } /// public FileOffset EndOffset { get; set; } /// /// Constructor /// /// User resource type public UserResourceData(UserResourceType type) { this.type = type; } /// public abstract void WriteData(BinaryWriter writer, IFormatter formatter); } /// /// Binary data /// public sealed class BinaryResourceData : UserResourceData { byte[] data; /// /// Gets the raw data /// public byte[] Data { get { return data; } } /// /// Constructor /// /// User resource type /// Raw serialized data public BinaryResourceData(UserResourceType type, byte[] data) : base(type) { this.data = data; } /// public override void WriteData(BinaryWriter writer, IFormatter formatter) { writer.Write(data); } /// public override string ToString() { return string.Format("Binary: Length: {0}", data.Length); } } } dnlib-2.1_VS2010/src/DotNet/Resources/UserResourceType.cs000066400000000000000000000015601325033663500231440ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Resources { /// /// User resource type /// public sealed class UserResourceType { readonly string name; readonly ResourceTypeCode code; /// /// Full name including assembly of type /// public string Name { get { return name; } } /// /// User type code /// public ResourceTypeCode Code { get { return code; } } /// /// Constructor /// /// Full name including assembly of type /// User type code public UserResourceType(string name, ResourceTypeCode code) { this.name = name; this.code = code; } /// public override string ToString() { return string.Format("{0:X2} {1}", (int)code, name); } } } dnlib-2.1_VS2010/src/DotNet/SecurityAction.cs000066400000000000000000000025711325033663500206520ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Security action. See CorHdr.h/CorDeclSecurity /// public enum SecurityAction : short { /// Mask allows growth of enum. ActionMask = 0x001F, /// ActionNil = 0x0000, /// Request = 0x0001, /// Demand = 0x0002, /// Assert = 0x0003, /// Deny = 0x0004, /// PermitOnly = 0x0005, /// LinktimeCheck = 0x0006, /// LinkDemand = LinktimeCheck, /// InheritanceCheck = 0x0007, /// InheritDemand = InheritanceCheck, /// RequestMinimum = 0x0008, /// RequestOptional = 0x0009, /// RequestRefuse = 0x000A, /// Persisted grant set at prejit time PrejitGrant = 0x000B, /// Persisted grant set at prejit time PreJitGrant = PrejitGrant, /// Persisted denied set at prejit time PrejitDenied = 0x000C, /// Persisted denied set at prejit time PreJitDeny = PrejitDenied, /// NonCasDemand = 0x000D, /// NonCasLinkDemand = 0x000E, /// NonCasInheritance = 0x000F, /// Maximum legal value MaximumValue = 0x000F, } } dnlib-2.1_VS2010/src/DotNet/SecurityAttribute.cs000066400000000000000000000065041325033663500214000ustar00rootroot00000000000000// 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 namespace dnlib.DotNet { /// /// A DeclSecurity security attribute /// public sealed class SecurityAttribute : ICustomAttribute { ITypeDefOrRef attrType; readonly ThreadSafe.IList namedArguments; /// /// Gets/sets the attribute type /// public ITypeDefOrRef AttributeType { get { return attrType; } set { attrType = value; } } /// /// Gets the full name of the attribute type /// public string TypeFullName { get { var at = attrType; return at == null ? string.Empty : at.FullName; } } /// /// Gets all named arguments (field and property values) /// public ThreadSafe.IList NamedArguments { get { return namedArguments; } } /// /// true if is not empty /// public bool HasNamedArguments { get { return namedArguments.Count > 0; } } /// /// Gets all s that are field arguments /// public IEnumerable Fields { get { foreach (var namedArg in namedArguments.GetSafeEnumerable()) { if (namedArg.IsField) yield return namedArg; } } } /// /// Gets all s that are property arguments /// public IEnumerable Properties { get { foreach (var namedArg in namedArguments.GetSafeEnumerable()) { if (namedArg.IsProperty) yield return namedArg; } } } /// /// Creates a from an XML string. /// /// Owner module /// XML /// A new instance public static SecurityAttribute CreateFromXml(ModuleDef module, string xml) { var attrType = module.CorLibTypes.GetTypeRef("System.Security.Permissions", "PermissionSetAttribute"); var utf8Xml = new UTF8String(xml); var namedArg = new CANamedArgument(false, module.CorLibTypes.String, "XML", new CAArgument(module.CorLibTypes.String, utf8Xml)); var list = ThreadSafeListCreator.Create(namedArg); return new SecurityAttribute(attrType, list); } /// /// Default constructor /// public SecurityAttribute() : this(null, null) { } /// /// Constructor /// /// Attribute type public SecurityAttribute(ITypeDefOrRef attrType) : this(attrType, null) { } /// /// Constructor /// /// Attribute type /// Named arguments that will be owned by this instance public SecurityAttribute(ITypeDefOrRef attrType, IList namedArguments) { this.attrType = attrType; this.namedArguments = ThreadSafeListCreator.MakeThreadSafe(namedArguments ?? new List()); } /// public override string ToString() { return TypeFullName; } } } dnlib-2.1_VS2010/src/DotNet/SerializationType.cs000066400000000000000000000026271325033663500213660ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// See CorSerializationType/CorHdr.h /// enum SerializationType : byte { /// Undefined = 0, /// System.Boolean Boolean = ElementType.Boolean, /// System.Char Char = ElementType.Char, /// System.SByte I1 = ElementType.I1, /// System.Byte U1 = ElementType.U1, /// System.Int16 I2 = ElementType.I2, /// System.UInt16 U2 = ElementType.U2, /// System.Int32 I4 = ElementType.I4, /// System.UInt32 U4 = ElementType.U4, /// System.Int64 I8 = ElementType.I8, /// System.UInt64 U8 = ElementType.U8, /// System.Single R4 = ElementType.R4, /// System.Double R8 = ElementType.R8, /// System.String String = ElementType.String, /// Single-dimension, zero lower bound array ([]) SZArray = ElementType.SZArray, /// System.Type Type = 0x50, /// Boxed value type TaggedObject= 0x51, /// A field Field = 0x53, /// A property Property = 0x54, /// An enum Enum = 0x55, } } dnlib-2.1_VS2010/src/DotNet/SigComparer.cs000066400000000000000000004445061325033663500201300ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Reflection; namespace dnlib.DotNet { /// /// Compares types /// public sealed class TypeEqualityComparer : IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer { readonly SigComparerOptions options; /// /// Default instance /// public static readonly TypeEqualityComparer Instance = new TypeEqualityComparer(0); /// /// Case insensitive names /// public static readonly TypeEqualityComparer CaseInsensitive = new TypeEqualityComparer(SigComparerOptions.CaseInsensitiveAll); /// /// Constructor /// /// Comparison options public TypeEqualityComparer(SigComparerOptions options) { this.options = options; } /// public bool Equals(IType x, IType y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(IType obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(ITypeDefOrRef x, ITypeDefOrRef y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(ITypeDefOrRef obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(TypeRef x, TypeRef y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(TypeRef obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(TypeDef x, TypeDef y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(TypeDef obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(TypeSpec x, TypeSpec y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(TypeSpec obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(TypeSig x, TypeSig y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(TypeSig obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(ExportedType x, ExportedType y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(ExportedType obj) { return new SigComparer(options).GetHashCode(obj); } } /// /// Compares fields /// public sealed class FieldEqualityComparer : IEqualityComparer, IEqualityComparer, IEqualityComparer { readonly SigComparerOptions options; /// /// Compares the declaring types /// public static readonly FieldEqualityComparer CompareDeclaringTypes = new FieldEqualityComparer(SigComparerOptions.CompareMethodFieldDeclaringType); /// /// Doesn't compare the declaring types /// public static readonly FieldEqualityComparer DontCompareDeclaringTypes = new FieldEqualityComparer(0); /// /// Compares the declaring types, case insensitive names /// public static readonly FieldEqualityComparer CaseInsensitiveCompareDeclaringTypes = new FieldEqualityComparer(SigComparerOptions.CompareMethodFieldDeclaringType | SigComparerOptions.CaseInsensitiveAll); /// /// Doesn't compare the declaring types, case insensitive names /// public static readonly FieldEqualityComparer CaseInsensitiveDontCompareDeclaringTypes = new FieldEqualityComparer(SigComparerOptions.CaseInsensitiveAll); /// /// Constructor /// /// Comparison options public FieldEqualityComparer(SigComparerOptions options) { this.options = options; } /// public bool Equals(IField x, IField y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(IField obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(FieldDef x, FieldDef y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(FieldDef obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(MemberRef x, MemberRef y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(MemberRef obj) { return new SigComparer(options).GetHashCode(obj); } } /// /// Compares methods /// public sealed class MethodEqualityComparer : IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer { readonly SigComparerOptions options; /// /// Compares the declaring types /// public static readonly MethodEqualityComparer CompareDeclaringTypes = new MethodEqualityComparer(SigComparerOptions.CompareMethodFieldDeclaringType); /// /// Doesn't compare the declaring types /// public static readonly MethodEqualityComparer DontCompareDeclaringTypes = new MethodEqualityComparer(0); /// /// Compares the declaring types, case insensitive names /// public static readonly MethodEqualityComparer CaseInsensitiveCompareDeclaringTypes = new MethodEqualityComparer(SigComparerOptions.CompareMethodFieldDeclaringType | SigComparerOptions.CaseInsensitiveAll); /// /// Doesn't compare the declaring types, case insensitive names /// public static readonly MethodEqualityComparer CaseInsensitiveDontCompareDeclaringTypes = new MethodEqualityComparer(SigComparerOptions.CaseInsensitiveAll); /// /// Constructor /// /// Comparison options public MethodEqualityComparer(SigComparerOptions options) { this.options = options; } /// public bool Equals(IMethod x, IMethod y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(IMethod obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(IMethodDefOrRef x, IMethodDefOrRef y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(IMethodDefOrRef obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(MethodDef x, MethodDef y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(MethodDef obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(MemberRef x, MemberRef y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(MemberRef obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(MethodSpec x, MethodSpec y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(MethodSpec obj) { return new SigComparer(options).GetHashCode(obj); } } /// /// Compares properties /// public sealed class PropertyEqualityComparer : IEqualityComparer { readonly SigComparerOptions options; /// /// Compares the declaring types /// public static readonly PropertyEqualityComparer CompareDeclaringTypes = new PropertyEqualityComparer(SigComparerOptions.ComparePropertyDeclaringType); /// /// Doesn't compare the declaring types /// public static readonly PropertyEqualityComparer DontCompareDeclaringTypes = new PropertyEqualityComparer(0); /// /// Compares the declaring types, case insensitive names /// public static readonly PropertyEqualityComparer CaseInsensitiveCompareDeclaringTypes = new PropertyEqualityComparer(SigComparerOptions.ComparePropertyDeclaringType | SigComparerOptions.CaseInsensitiveAll); /// /// Doesn't compare the declaring types, case insensitive names /// public static readonly PropertyEqualityComparer CaseInsensitiveDontCompareDeclaringTypes = new PropertyEqualityComparer(SigComparerOptions.CaseInsensitiveAll); /// /// Constructor /// /// Comparison options public PropertyEqualityComparer(SigComparerOptions options) { this.options = options; } /// public bool Equals(PropertyDef x, PropertyDef y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(PropertyDef obj) { return new SigComparer(options).GetHashCode(obj); } } /// /// Compares events /// public sealed class EventEqualityComparer : IEqualityComparer { readonly SigComparerOptions options; /// /// Compares the declaring types /// public static readonly EventEqualityComparer CompareDeclaringTypes = new EventEqualityComparer(SigComparerOptions.CompareEventDeclaringType); /// /// Doesn't compare the declaring types /// public static readonly EventEqualityComparer DontCompareDeclaringTypes = new EventEqualityComparer(0); /// /// Compares the declaring types, case insensitive names /// public static readonly EventEqualityComparer CaseInsensitiveCompareDeclaringTypes = new EventEqualityComparer(SigComparerOptions.CompareEventDeclaringType | SigComparerOptions.CaseInsensitiveAll); /// /// Doesn't compare the declaring types, case insensitive names /// public static readonly EventEqualityComparer CaseInsensitiveDontCompareDeclaringTypes = new EventEqualityComparer(SigComparerOptions.CaseInsensitiveAll); /// /// Constructor /// /// Comparison options public EventEqualityComparer(SigComparerOptions options) { this.options = options; } /// public bool Equals(EventDef x, EventDef y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(EventDef obj) { return new SigComparer(options).GetHashCode(obj); } } /// /// Compares calling convention signatures /// public sealed class SignatureEqualityComparer : IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer, IEqualityComparer { readonly SigComparerOptions options; /// /// Default instance /// public static readonly SignatureEqualityComparer Instance = new SignatureEqualityComparer(0); /// /// Case insensitive names /// public static readonly SignatureEqualityComparer CaseInsensitive = new SignatureEqualityComparer(SigComparerOptions.CaseInsensitiveAll); /// /// Constructor /// /// Comparison options public SignatureEqualityComparer(SigComparerOptions options) { this.options = options; } /// public bool Equals(CallingConventionSig x, CallingConventionSig y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(CallingConventionSig obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(MethodBaseSig x, MethodBaseSig y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(MethodBaseSig obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(MethodSig x, MethodSig y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(MethodSig obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(PropertySig x, PropertySig y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(PropertySig obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(FieldSig x, FieldSig y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(FieldSig obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(LocalSig x, LocalSig y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(LocalSig obj) { return new SigComparer(options).GetHashCode(obj); } /// public bool Equals(GenericInstMethodSig x, GenericInstMethodSig y) { return new SigComparer(options).Equals(x, y); } /// public int GetHashCode(GenericInstMethodSig obj) { return new SigComparer(options).GetHashCode(obj); } } /// /// Decides how to compare types, sigs, etc /// [Flags] public enum SigComparerOptions : uint { /// /// Don't compare a type's (assembly/module) scope /// DontCompareTypeScope = 1, /// /// Compares a method/field's declaring type. /// CompareMethodFieldDeclaringType = 2, /// /// Compares a property's declaring type /// ComparePropertyDeclaringType = 4, /// /// Compares an event's declaring type /// CompareEventDeclaringType = 8, /// /// Compares method / field / property / event declaring types /// CompareDeclaringTypes = CompareMethodFieldDeclaringType | ComparePropertyDeclaringType | CompareEventDeclaringType, /// /// Compares parameters after a sentinel in method sigs. Should not be enabled when /// comparing s against s since it's /// not possible to get those sentinel params from a . /// CompareSentinelParams = 0x10, /// /// Compares assembly public key token /// CompareAssemblyPublicKeyToken = 0x20, /// /// Compares assembly version /// CompareAssemblyVersion = 0x40, /// /// Compares assembly locale /// CompareAssemblyLocale = 0x80, /// /// If set, a and an can reference the /// global <Module> type. /// TypeRefCanReferenceGlobalType = 0x100, /// /// Don't compare a method/property's return type /// DontCompareReturnType = 0x200, /// /// If set, all generic parameters are replaced with their generic arguments prior /// to comparing types. You should enable this when comparing a method, field, property /// or an event to a , , /// or an if the owner type could /// be a generic instance type. /// SubstituteGenericParameters = 0x400, /// /// Type namespaces are case insensitive /// CaseInsensitiveTypeNamespaces = 0x800, /// /// Type names (not namespaces) are case insensitive /// CaseInsensitiveTypeNames = 0x1000, /// /// Type names and namespaces are case insensitive /// CaseInsensitiveTypes = CaseInsensitiveTypeNamespaces | CaseInsensitiveTypeNames, /// /// Method and field names are case insensitive /// CaseInsensitiveMethodFieldNames = 0x2000, /// /// Property names are case insensitive /// CaseInsensitivePropertyNames = 0x4000, /// /// Event names are case insensitive /// CaseInsensitiveEventNames = 0x8000, /// /// Type namespaces, type names, method names, field names, property names /// and event names are all case insensitive /// CaseInsensitiveAll = CaseInsensitiveTypeNamespaces | CaseInsensitiveTypeNames | CaseInsensitiveMethodFieldNames | CaseInsensitivePropertyNames | CaseInsensitiveEventNames, /// /// A field that is can compare equal to /// a /// PrivateScopeFieldIsComparable = 0x10000, /// /// A method that is can compare equal to /// a /// PrivateScopeMethodIsComparable = 0x20000, /// /// A field that is and a method that is /// can compare equal to a /// PrivateScopeIsComparable = PrivateScopeFieldIsComparable | PrivateScopeMethodIsComparable, /// /// Raw (bit by bit) comparison of signatures. This matches what the CLR does when it /// compares signatures. This means that metadata tokens will be compared. /// RawSignatureCompare = 0x40000, /// /// Ignore required and optional modifiers when comparing s. /// They're already ignored when comparing eg. a with a /// . /// IgnoreModifiers = 0x80000, /// /// By default, all module and assembly compares when they're both the system library /// (eg. mscorlib or System.Runtime.dll) return true, even if they're really different, /// eg. mscorlib (.NET 2.0) vs mscorlib (Windows CE). If this flag is set, the system /// library is compared just like any other module/assembly. /// MscorlibIsNotSpecial = 0x100000, /// /// Don't project CLR compatible WinMD references back to the original CLR type/method before comparing /// DontProjectWinMDRefs = 0x200000, /// /// Don't check type equivalence when comparing types. Starting with .NET 4.0, two different /// types can be considered equivalent if eg. a TypeIdentifierAttribute is used. /// DontCheckTypeEquivalence = 0x400000, } /// /// Compares types, signatures, methods, fields, properties, events /// public struct SigComparer { const int HASHCODE_MAGIC_GLOBAL_TYPE = 1654396648; const int HASHCODE_MAGIC_NESTED_TYPE = -1049070942; const int HASHCODE_MAGIC_ET_MODULE = -299744851; const int HASHCODE_MAGIC_ET_VALUEARRAY = -674970533; const int HASHCODE_MAGIC_ET_GENERICINST = -2050514639; const int HASHCODE_MAGIC_ET_VAR = 1288450097; const int HASHCODE_MAGIC_ET_MVAR = -990598495; const int HASHCODE_MAGIC_ET_ARRAY = -96331531; const int HASHCODE_MAGIC_ET_SZARRAY = 871833535; const int HASHCODE_MAGIC_ET_BYREF = -634749586; const int HASHCODE_MAGIC_ET_PTR = 1976400808; const int HASHCODE_MAGIC_ET_SENTINEL = 68439620; RecursionCounter recursionCounter; SigComparerOptions options; GenericArguments genericArguments; readonly ModuleDef sourceModule; bool DontCompareTypeScope { get { return (options & SigComparerOptions.DontCompareTypeScope) != 0; } } bool CompareMethodFieldDeclaringType { get { return (options & SigComparerOptions.CompareMethodFieldDeclaringType) != 0; } } bool ComparePropertyDeclaringType { get { return (options & SigComparerOptions.ComparePropertyDeclaringType) != 0; } } bool CompareEventDeclaringType { get { return (options & SigComparerOptions.CompareEventDeclaringType) != 0; } } bool CompareSentinelParams { get { return (options & SigComparerOptions.CompareSentinelParams) != 0; } } bool CompareAssemblyPublicKeyToken { get { return (options & SigComparerOptions.CompareAssemblyPublicKeyToken) != 0; } } bool CompareAssemblyVersion { get { return (options & SigComparerOptions.CompareAssemblyVersion) != 0; } } bool CompareAssemblyLocale { get { return (options & SigComparerOptions.CompareAssemblyLocale) != 0; } } bool TypeRefCanReferenceGlobalType { get { return (options & SigComparerOptions.TypeRefCanReferenceGlobalType) != 0; } } bool DontCompareReturnType { get { return (options & SigComparerOptions.DontCompareReturnType) != 0; } } bool SubstituteGenericParameters { get { return (options & SigComparerOptions.SubstituteGenericParameters) != 0; } } bool CaseInsensitiveTypeNamespaces { get { return (options & SigComparerOptions.CaseInsensitiveTypeNamespaces) != 0; } } bool CaseInsensitiveTypeNames { get { return (options & SigComparerOptions.CaseInsensitiveTypeNames) != 0; } } bool CaseInsensitiveMethodFieldNames { get { return (options & SigComparerOptions.CaseInsensitiveMethodFieldNames) != 0; } } bool CaseInsensitivePropertyNames { get { return (options & SigComparerOptions.CaseInsensitivePropertyNames) != 0; } } bool CaseInsensitiveEventNames { get { return (options & SigComparerOptions.CaseInsensitiveEventNames) != 0; } } bool PrivateScopeFieldIsComparable { get { return (options & SigComparerOptions.PrivateScopeFieldIsComparable) != 0; } } bool PrivateScopeMethodIsComparable { get { return (options & SigComparerOptions.PrivateScopeMethodIsComparable) != 0; } } bool RawSignatureCompare { get { return (options & SigComparerOptions.RawSignatureCompare) != 0; } } bool IgnoreModifiers { get { return (options & SigComparerOptions.IgnoreModifiers) != 0; } } bool MscorlibIsNotSpecial { get { return (options & SigComparerOptions.MscorlibIsNotSpecial) != 0; } } bool DontProjectWinMDRefs { get { return (options & SigComparerOptions.DontProjectWinMDRefs) != 0; } } bool DontCheckTypeEquivalence { get { return (options & SigComparerOptions.DontCheckTypeEquivalence) != 0; } } /// /// Constructor /// /// Comparison options public SigComparer(SigComparerOptions options) : this(options, null) { } /// /// Constructor /// /// Comparison options /// The module which the comparison take place in. public SigComparer(SigComparerOptions options, ModuleDef sourceModule) { this.recursionCounter = new RecursionCounter(); this.options = options; this.genericArguments = null; this.sourceModule = sourceModule; } /// /// is mapped to , so use /// the same hash code for both /// int GetHashCode_FnPtr_SystemIntPtr() { // ******************************************** // IMPORTANT: This must match GetHashCode(TYPE) // ******************************************** return GetHashCode_TypeNamespace("System") + GetHashCode_TypeName("IntPtr"); } bool Equals_Names(bool caseInsensitive, UTF8String a, UTF8String b) { if (caseInsensitive) return UTF8String.ToSystemStringOrEmpty(a).Equals(UTF8String.ToSystemStringOrEmpty(b), StringComparison.OrdinalIgnoreCase); return UTF8String.Equals(a, b); } bool Equals_Names(bool caseInsensitive, string a, string b) { if (caseInsensitive) return (a ?? string.Empty).Equals(b ?? string.Empty, StringComparison.OrdinalIgnoreCase); return (a ?? string.Empty) == (b ?? string.Empty); } int GetHashCode_Name(bool caseInsensitive, string a) { if (caseInsensitive) return (a ?? string.Empty).ToUpperInvariant().GetHashCode(); return (a ?? string.Empty).GetHashCode(); } bool Equals_TypeNamespaces(UTF8String a, UTF8String b) { return Equals_Names(CaseInsensitiveTypeNamespaces, a, b); } bool Equals_TypeNamespaces(UTF8String a, string b) { return Equals_Names(CaseInsensitiveTypeNamespaces, UTF8String.ToSystemStringOrEmpty(a), b); } int GetHashCode_TypeNamespace(UTF8String a) { return GetHashCode_Name(CaseInsensitiveTypeNamespaces, UTF8String.ToSystemStringOrEmpty(a)); } int GetHashCode_TypeNamespace(string a) { return GetHashCode_Name(CaseInsensitiveTypeNamespaces, a); } bool Equals_TypeNames(UTF8String a, UTF8String b) { return Equals_Names(CaseInsensitiveTypeNames, a, b); } bool Equals_TypeNames(UTF8String a, string b) { return Equals_Names(CaseInsensitiveTypeNames, UTF8String.ToSystemStringOrEmpty(a), b); } int GetHashCode_TypeName(UTF8String a) { return GetHashCode_Name(CaseInsensitiveTypeNames, UTF8String.ToSystemStringOrEmpty(a)); } int GetHashCode_TypeName(string a) { return GetHashCode_Name(CaseInsensitiveTypeNames, a); } bool Equals_MethodFieldNames(UTF8String a, UTF8String b) { return Equals_Names(CaseInsensitiveMethodFieldNames, a, b); } bool Equals_MethodFieldNames(UTF8String a, string b) { return Equals_Names(CaseInsensitiveMethodFieldNames, UTF8String.ToSystemStringOrEmpty(a), b); } int GetHashCode_MethodFieldName(UTF8String a) { return GetHashCode_Name(CaseInsensitiveMethodFieldNames, UTF8String.ToSystemStringOrEmpty(a)); } int GetHashCode_MethodFieldName(string a) { return GetHashCode_Name(CaseInsensitiveMethodFieldNames, a); } bool Equals_PropertyNames(UTF8String a, UTF8String b) { return Equals_Names(CaseInsensitivePropertyNames, a, b); } bool Equals_PropertyNames(UTF8String a, string b) { return Equals_Names(CaseInsensitivePropertyNames, UTF8String.ToSystemStringOrEmpty(a), b); } int GetHashCode_PropertyName(UTF8String a) { return GetHashCode_Name(CaseInsensitivePropertyNames, UTF8String.ToSystemStringOrEmpty(a)); } int GetHashCode_PropertyName(string a) { return GetHashCode_Name(CaseInsensitivePropertyNames, a); } bool Equals_EventNames(UTF8String a, UTF8String b) { return Equals_Names(CaseInsensitiveEventNames, a, b); } bool Equals_EventNames(UTF8String a, string b) { return Equals_Names(CaseInsensitiveEventNames, UTF8String.ToSystemStringOrEmpty(a), b); } int GetHashCode_EventName(UTF8String a) { return GetHashCode_Name(CaseInsensitiveEventNames, UTF8String.ToSystemStringOrEmpty(a)); } int GetHashCode_EventName(string a) { return GetHashCode_Name(CaseInsensitiveEventNames, a); } SigComparerOptions ClearOptions(SigComparerOptions flags) { var old = options; options &= ~flags; return old; } SigComparerOptions SetOptions(SigComparerOptions flags) { var old = options; options |= flags; return old; } void RestoreOptions(SigComparerOptions oldFlags) { options = oldFlags; } void InitializeGenericArguments() { if (genericArguments == null) genericArguments = new GenericArguments(); } static GenericInstSig GetGenericInstanceType(IMemberRefParent parent) { var ts = parent as TypeSpec; if (ts == null) return null; return ts.TypeSig.RemoveModifiers() as GenericInstSig; } bool Equals(IAssembly aAsm, IAssembly bAsm, TypeRef b) { if (Equals(aAsm, bAsm)) return true; // Could be an exported type. Resolve it and check again. var td = b.Resolve(sourceModule); return td != null && Equals(aAsm, td.Module.Assembly); } bool Equals(IAssembly aAsm, IAssembly bAsm, ExportedType b) { if (Equals(aAsm, bAsm)) return true; var td = b.Resolve(); return td != null && Equals(aAsm, td.Module.Assembly); } bool Equals(IAssembly aAsm, TypeRef a, IAssembly bAsm, TypeRef b) { if (Equals(aAsm, bAsm)) return true; // Could be exported types. Resolve them and check again. var tda = a.Resolve(sourceModule); var tdb = b.Resolve(sourceModule); return tda != null && tdb != null && Equals(tda.Module.Assembly, tdb.Module.Assembly); } bool Equals(IAssembly aAsm, ExportedType a, IAssembly bAsm, ExportedType b) { if (Equals(aAsm, bAsm)) return true; var tda = a.Resolve(); var tdb = b.Resolve(); return tda != null && tdb != null && Equals(tda.Module.Assembly, tdb.Module.Assembly); } bool Equals(IAssembly aAsm, TypeRef a, IAssembly bAsm, ExportedType b) { if (Equals(aAsm, bAsm)) return true; // Could be an exported type. Resolve it and check again. var tda = a.Resolve(sourceModule); var tdb = b.Resolve(); return tda != null && tdb != null && Equals(tda.Module.Assembly, tdb.Module.Assembly); } bool Equals(TypeDef a, IModule bMod, TypeRef b) { if (Equals(a.Module, bMod) && Equals(a.DefinitionAssembly, b.DefinitionAssembly)) return true; // Could be an exported type. Resolve it and check again. var td = b.Resolve(sourceModule); if (td == null) return false; if (!DontCheckTypeEquivalence) { if (TIAHelper.Equivalent(a, td)) return true; } return Equals(a.Module, td.Module) && Equals(a.DefinitionAssembly, td.DefinitionAssembly); } bool Equals(TypeDef a, FileDef bFile, ExportedType b) { if (Equals(a.Module, bFile) && Equals(a.DefinitionAssembly, b.DefinitionAssembly)) return true; var td = b.Resolve(); return td != null && Equals(a.Module, td.Module) && Equals(a.DefinitionAssembly, td.DefinitionAssembly); } bool TypeDefScopeEquals(TypeDef a, TypeDef b) { if (a == null || b == null) return false; if (!DontCheckTypeEquivalence) { if (TIAHelper.Equivalent(a, b)) return true; } return Equals(a.Module, b.Module); } bool Equals(TypeRef a, IModule ma, TypeRef b, IModule mb) { if (Equals(ma, mb) && Equals(a.DefinitionAssembly, b.DefinitionAssembly)) return true; // Could be exported types. Resolve them and check again. var tda = a.Resolve(sourceModule); var tdb = b.Resolve(sourceModule); return tda != null && tdb != null && Equals(tda.Module, tdb.Module) && Equals(tda.DefinitionAssembly, tdb.DefinitionAssembly); } bool Equals(TypeRef a, IModule ma, ExportedType b, FileDef fb) { if (Equals(ma, fb) && Equals(a.DefinitionAssembly, b.DefinitionAssembly)) return true; // Could be an exported type. Resolve it and check again. var tda = a.Resolve(sourceModule); var tdb = b.Resolve(); return tda != null && tdb != null && Equals(tda.Module, tdb.Module) && Equals(tda.DefinitionAssembly, tdb.DefinitionAssembly); } bool Equals(Assembly aAsm, IAssembly bAsm, TypeRef b) { if (Equals(bAsm, aAsm)) return true; // Could be an exported type. Resolve it and check again. var td = b.Resolve(sourceModule); return td != null && Equals(td.Module.Assembly, aAsm); } bool Equals(Assembly aAsm, IAssembly bAsm, ExportedType b) { if (Equals(bAsm, aAsm)) return true; var td = b.Resolve(); return td != null && Equals(td.Module.Assembly, aAsm); } bool Equals(Type a, IModule bMod, TypeRef b) { if (Equals(bMod, a.Module) && Equals(b.DefinitionAssembly, a.Assembly)) return true; // Could be an exported type. Resolve it and check again. var td = b.Resolve(sourceModule); return td != null && Equals(td.Module, a.Module) && Equals(td.DefinitionAssembly, a.Assembly); } bool Equals(Type a, FileDef bFile, ExportedType b) { if (Equals(bFile, a.Module) && Equals(b.DefinitionAssembly, a.Assembly)) return true; var td = b.Resolve(); return td != null && Equals(td.Module, a.Module) && Equals(td.DefinitionAssembly, a.Assembly); } /// /// Compare members /// /// Member #1 /// Member #2 /// true if same, false otherwise public bool Equals(IMemberRef a, IMemberRef b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; IType ta, tb; IField fa, fb; IMethod ma, mb; PropertyDef pa, pb; EventDef ea, eb; if ((ta = a as IType) != null && (tb = b as IType) != null) result = Equals(ta, tb); else if ((fa = a as IField) != null && (fb = b as IField) != null && fa.IsField && fb.IsField) result = Equals(fa, fb); else if ((ma = a as IMethod) != null && (mb = b as IMethod) != null) result = Equals(ma, mb); else if ((pa = a as PropertyDef) != null && (pb = b as PropertyDef) != null) result = Equals(pa, pb); else if ((ea = a as EventDef) != null && (eb = b as EventDef) != null) result = Equals(ea, eb); else result = false; recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a member /// /// The member /// The hash code public int GetHashCode(IMemberRef a) { if (a == null) return 0; if (!recursionCounter.Increment()) return 0; int result; IType ta; IField fa; IMethod ma; PropertyDef pa; EventDef ea; if ((ta = a as IType) != null) result = GetHashCode(ta); else if ((fa = a as IField) != null) result = GetHashCode(fa); else if ((ma = a as IMethod) != null) result = GetHashCode(ma); else if ((pa = a as PropertyDef) != null) result = GetHashCode(pa); else if ((ea = a as EventDef) != null) result = GetHashCode(ea); else result = 0; // Should never be reached recursionCounter.Decrement(); return result; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(ITypeDefOrRef a, ITypeDefOrRef b) { return Equals((IType)a, (IType)b); } /// /// Gets the hash code of a type /// /// The type /// The hash code public int GetHashCode(ITypeDefOrRef a) { return GetHashCode((IType)a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(IType a, IType b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; TypeDef tda, tdb; TypeRef tra, trb; TypeSpec tsa, tsb; TypeSig sa, sb; ExportedType eta, etb; if ((tda = a as TypeDef) != null & (tdb = b as TypeDef) != null) result = Equals(tda, tdb); else if ((tra = a as TypeRef) != null & (trb = b as TypeRef) != null) result = Equals(tra, trb); else if ((tsa = a as TypeSpec) != null & (tsb = b as TypeSpec) != null) result = Equals(tsa, tsb); else if ((sa = a as TypeSig) != null & (sb = b as TypeSig) != null) result = Equals(sa, sb); else if ((eta = a as ExportedType) != null & (etb = b as ExportedType) != null) result = Equals(eta, etb); else if (tda != null && trb != null) result = Equals(tda, trb); // TypeDef vs TypeRef else if (tra != null && tdb != null) result = Equals(tdb, tra); // TypeDef vs TypeRef else if (tda != null && tsb != null) result = Equals(tda, tsb); // TypeDef vs TypeSpec else if (tsa != null && tdb != null) result = Equals(tdb, tsa); // TypeDef vs TypeSpec else if (tda != null && sb != null) result = Equals(tda, sb); // TypeDef vs TypeSig else if (sa != null && tdb != null) result = Equals(tdb, sa); // TypeDef vs TypeSig else if (tda != null && etb != null) result = Equals(tda, etb); // TypeDef vs ExportedType else if (eta != null && tdb != null) result = Equals(tdb, eta); // TypeDef vs ExportedType else if (tra != null && tsb != null) result = Equals(tra, tsb); // TypeRef vs TypeSpec else if (tsa != null && trb != null) result = Equals(trb, tsa); // TypeRef vs TypeSpec else if (tra != null && sb != null) result = Equals(tra, sb); // TypeRef vs TypeSig else if (sa != null && trb != null) result = Equals(trb, sa); // TypeRef vs TypeSig else if (tra != null && etb != null) result = Equals(tra, etb); // TypeRef vs ExportedType else if (eta != null && trb != null) result = Equals(trb, eta); // TypeRef vs ExportedType else if (tsa != null && sb != null) result = Equals(tsa, sb); // TypeSpec vs TypeSig else if (sa != null && tsb != null) result = Equals(tsb, sa); // TypeSpec vs TypeSig else if (tsa != null && etb != null) result = Equals(tsa, etb); // TypeSpec vs ExportedType else if (eta != null && tsb != null) result = Equals(tsb, eta); // TypeSpec vs ExportedType else if (sa != null && etb != null) result = Equals(sa, etb); // TypeSig vs ExportedType else if (eta != null && sb != null) result = Equals(sb, eta); // TypeSig vs ExportedType else result = false; // Should never be reached recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a type /// /// The type /// The hash code public int GetHashCode(IType a) { if (a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash; TypeDef td; TypeRef tr; TypeSpec ts; TypeSig sig; ExportedType et; if ((td = a as TypeDef) != null) hash = GetHashCode(td); else if ((tr = a as TypeRef) != null) hash = GetHashCode(tr); else if ((ts = a as TypeSpec) != null) hash = GetHashCode(ts); else if ((sig = a as TypeSig) != null) hash = GetHashCode(sig); else if ((et = a as ExportedType) != null) hash = GetHashCode(et); else hash = 0; // Should never be reached recursionCounter.Decrement(); return hash; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeRef a, TypeDef b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeDef a, TypeRef b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; IModule bMod; AssemblyRef bAsm; TypeRef dtb; if (!DontProjectWinMDRefs) { var tra = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; if (tra != null) { result = Equals(tra, b); goto exit; } } var scope = b.ResolutionScope; if (!Equals_TypeNames(a.Name, b.Name) || !Equals_TypeNamespaces(a.Namespace, b.Namespace)) result = false; else if ((dtb = scope as TypeRef) != null) // nested type result = Equals(a.DeclaringType, dtb); // Compare enclosing types else if (a.DeclaringType != null) { // a is nested, b isn't result = false; } else if (DontCompareTypeScope) result = true; else if ((bMod = scope as IModule) != null) // 'b' is defined in the same assembly as 'a' result = Equals(a, bMod, b); else if ((bAsm = scope as AssemblyRef) != null) { var aMod = a.Module; result = aMod != null && Equals(aMod.Assembly, bAsm, b); if (!result) { if (!DontCheckTypeEquivalence) { var tdb = b.Resolve(); result = TypeDefScopeEquals(a, tdb); } } } else { result = false; //TODO: Handle the case where scope == null } if (result && !TypeRefCanReferenceGlobalType && a.IsGlobalModuleType) result = false; exit: ; recursionCounter.Decrement(); return result; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(ExportedType a, TypeDef b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeDef a, ExportedType b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; ExportedType dtb; FileDef bFile; AssemblyRef bAsm; if (!DontProjectWinMDRefs) { var tra = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; if (tra != null) { result = Equals(tra, b); goto exit; } } var scope = b.Implementation; if (!Equals_TypeNames(a.Name, b.TypeName) || !Equals_TypeNamespaces(a.Namespace, b.TypeNamespace)) result = false; else if ((dtb = scope as ExportedType) != null) { // nested type result = Equals(a.DeclaringType, dtb); // Compare enclosing types } else if (a.DeclaringType != null) { result = false; // a is nested, b isn't } else if (DontCompareTypeScope) result = true; else { if ((bFile = scope as FileDef) != null) result = Equals(a, bFile, b); else if ((bAsm = scope as AssemblyRef) != null) { var aMod = a.Module; result = aMod != null && Equals(aMod.Assembly, bAsm, b); } else result = false; if (!result && !DontCheckTypeEquivalence) { var tdb = b.Resolve(); result = TypeDefScopeEquals(a, tdb); } } if (result && !TypeRefCanReferenceGlobalType && a.IsGlobalModuleType) result = false; exit: ; recursionCounter.Decrement(); return result; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeSpec a, TypeDef b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeDef a, TypeSpec b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; return Equals(a, b.TypeSig); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeSig a, TypeDef b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeDef a, TypeSig b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; //************************************************************* // If this code gets updated, update GetHashCode(TypeSig), // Equals(TypeRef,TypeSig) and Equals(TypeSig,ExportedType) too //************************************************************* var b2 = b as TypeDefOrRefSig; if (b2 != null) result = Equals(a, (IType)b2.TypeDefOrRef); else if (b is ModifierSig || b is PinnedSig) result = Equals(a, b.Next); else result = false; recursionCounter.Decrement(); return result; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeSpec a, TypeRef b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeRef a, TypeSpec b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; return Equals(a, b.TypeSig); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(ExportedType a, TypeRef b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeRef a, ExportedType b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; } bool result = Equals_TypeNames(a.Name, b.TypeName) && Equals_TypeNamespaces(a.Namespace, b.TypeNamespace) && EqualsScope(a, b); recursionCounter.Decrement(); return result; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeSig a, TypeRef b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeRef a, TypeSig b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; //************************************************************* // If this code gets updated, update GetHashCode(TypeSig), // Equals(TypeRef,TypeSig) and Equals(TypeSig,ExportedType) too //************************************************************* var b2 = b as TypeDefOrRefSig; if (b2 != null) result = Equals(a, (IType)b2.TypeDefOrRef); else if (b is ModifierSig || b is PinnedSig) result = Equals(a, b.Next); else result = false; recursionCounter.Decrement(); return result; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeSig a, TypeSpec b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeSpec a, TypeSig b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; return Equals(a.TypeSig, b); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(ExportedType a, TypeSpec b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeSpec a, ExportedType b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; return Equals(a.TypeSig, b); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(ExportedType a, TypeSig b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeSig a, ExportedType b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; //************************************************************* // If this code gets updated, update GetHashCode(TypeSig), // Equals(TypeRef,TypeSig) and Equals(TypeSig,ExportedType) too //************************************************************* var a2 = a as TypeDefOrRefSig; if (a2 != null) result = Equals(a2.TypeDefOrRef, b); else if (a is ModifierSig || a is PinnedSig) result = Equals(a.Next, b); else result = false; recursionCounter.Decrement(); return result; } int GetHashCodeGlobalType() { // We don't always know the name+namespace of the global type, eg. when it's // referenced by a ModuleRef. Use the same hash for all global types. return HASHCODE_MAGIC_GLOBAL_TYPE; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeRef a, TypeRef b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; } bool result = Equals_TypeNames(a.Name, b.Name) && Equals_TypeNamespaces(a.Namespace, b.Namespace) && EqualsResolutionScope(a, b); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a type /// /// The type /// The hash code public int GetHashCode(TypeRef a) { // ************************************************************************************ // IMPORTANT: This hash code must match the Type/TypeRef/TypeDef/ExportedType // hash code and GetHashCode_FnPtr_SystemIntPtr() method // ************************************************************************************ // See GetHashCode(Type) for the reason why null returns GetHashCodeGlobalType() if (a == null) return TypeRefCanReferenceGlobalType ? GetHashCodeGlobalType() : 0; if (!DontProjectWinMDRefs) a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; int hash; hash = GetHashCode_TypeName(a.Name); if (a.ResolutionScope is TypeRef) hash += HASHCODE_MAGIC_NESTED_TYPE; else hash += GetHashCode_TypeNamespace(a.Namespace); return hash; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(ExportedType a, ExportedType b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; } bool result = Equals_TypeNames(a.TypeName, b.TypeName) && Equals_TypeNamespaces(a.TypeNamespace, b.TypeNamespace) && EqualsImplementation(a, b); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a type /// /// The type /// The hash code public int GetHashCode(ExportedType a) { // ************************************************************************************ // IMPORTANT: This hash code must match the Type/TypeRef/TypeDef/ExportedType // hash code and GetHashCode_FnPtr_SystemIntPtr() method // ************************************************************************************ // See GetHashCode(Type) for the reason why null returns GetHashCodeGlobalType() if (a == null) return TypeRefCanReferenceGlobalType ? GetHashCodeGlobalType() : 0; if (!DontProjectWinMDRefs) a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; int hash; hash = GetHashCode_TypeName(a.TypeName); if (a.Implementation is ExportedType) hash += HASHCODE_MAGIC_NESTED_TYPE; else hash += GetHashCode_TypeNamespace(a.TypeNamespace); return hash; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeDef a, TypeDef b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; if (!DontProjectWinMDRefs) { var tra = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); var trb = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b); if (tra != null || trb != null) { result = Equals((IType)tra ?? a, (IType)trb ?? b); goto exit; } } result = Equals_TypeNames(a.Name, b.Name) && Equals_TypeNamespaces(a.Namespace, b.Namespace) && Equals(a.DeclaringType, b.DeclaringType) && (DontCompareTypeScope || TypeDefScopeEquals(a, b)); exit: ; recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a type /// /// The type /// The hash code public int GetHashCode(TypeDef a) { // ************************************************************************************ // IMPORTANT: This hash code must match the Type/TypeRef/TypeDef/ExportedType // hash code and GetHashCode_FnPtr_SystemIntPtr() method // ************************************************************************************ // See GetHashCode(Type) for the reason why null returns GetHashCodeGlobalType() if (a == null || a.IsGlobalModuleType) return GetHashCodeGlobalType(); if (!DontProjectWinMDRefs) { var tra = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); if (tra != null) return GetHashCode(tra); } int hash; hash = GetHashCode_TypeName(a.Name); if (a.DeclaringType != null) hash += HASHCODE_MAGIC_NESTED_TYPE; else hash += GetHashCode_TypeNamespace(a.Namespace); return hash; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeSpec a, TypeSpec b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result = Equals(a.TypeSig, b.TypeSig); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a type /// /// The type /// The hash code public int GetHashCode(TypeSpec a) { if (a == null) return 0; return GetHashCode(a.TypeSig); } /// /// Compares resolution scopes /// /// Type #1 /// Type #2 /// true if same, false otherwise bool EqualsResolutionScope(TypeRef a, TypeRef b) { if (a == b) return true; if (a == null || b == null) return false; var ra = a.ResolutionScope; var rb = b.ResolutionScope; if (ra == rb) return true; if (ra == null || rb == null) return false; if (!recursionCounter.Increment()) return false; bool result; TypeRef ea, eb; IModule ma, mb; AssemblyRef aa, ab; ModuleDef modDef; bool resolveCheck = true; // if one of them is a TypeRef, the other one must be too if ((ea = ra as TypeRef) != null | (eb = rb as TypeRef) != null) { result = Equals(ea, eb); resolveCheck = false; } else if (DontCompareTypeScope) result = true; // only compare if both are modules else if ((ma = ra as IModule) != null & (mb = rb as IModule) != null) result = Equals(a, ma, b, mb); // only compare if both are assemblies else if ((aa = ra as AssemblyRef) != null & (ab = rb as AssemblyRef) != null) result = Equals(aa, a, ab, b); else if (aa != null && rb is ModuleRef) { var bMod = b.Module; result = bMod != null && Equals(bMod.Assembly, b, aa, a); } else if (ab != null && ra is ModuleRef) { var aMod = a.Module; result = aMod != null && Equals(aMod.Assembly, a, ab, b); } else if (aa != null && (modDef = rb as ModuleDef) != null) result = Equals(modDef.Assembly, aa, a); else if (ab != null && (modDef = ra as ModuleDef) != null) result = Equals(modDef.Assembly, ab, b); else { result = false; resolveCheck = false; } if (!result && resolveCheck) { if (!DontCheckTypeEquivalence) { var td1 = a.Resolve(); var td2 = b.Resolve(); if (td1 != null && td2 != null) result = TypeDefScopeEquals(td1, td2); } } recursionCounter.Decrement(); return result; } /// /// Compares implementation /// /// Type #1 /// Type #2 /// true if same, false otherwise bool EqualsImplementation(ExportedType a, ExportedType b) { if (a == b) return true; if (a == null || b == null) return false; var ia = a.Implementation; var ib = b.Implementation; if (ia == ib) return true; if (ia == null || ib == null) return false; if (!recursionCounter.Increment()) return false; bool result; ExportedType ea, eb; FileDef fa, fb; AssemblyRef aa, ab; bool checkResolve = true; // if one of them is an ExportedType, the other one must be too if ((ea = ia as ExportedType) != null | (eb = ib as ExportedType) != null) { result = Equals(ea, eb); checkResolve = false; } else if (DontCompareTypeScope) result = true; // only compare if both are files else if ((fa = ia as FileDef) != null & (fb = ib as FileDef) != null) result = Equals(fa, fb); // only compare if both are assemblies else if ((aa = ia as AssemblyRef) != null & (ab = ib as AssemblyRef) != null) result = Equals(aa, a, ab, b); else if (fa != null && ab != null) result = Equals(a.DefinitionAssembly, ab, b); else if (fb != null && aa != null) result = Equals(b.DefinitionAssembly, aa, a); else { result = false; checkResolve = false; } if (!result && checkResolve && !DontCheckTypeEquivalence) { var td1 = a.Resolve(); var td2 = b.Resolve(); if (td1 != null && td2 != null) result = TypeDefScopeEquals(td1, td2); } recursionCounter.Decrement(); return result; } /// /// Compares resolution scope and implementation /// /// Type #1 /// Type #2 /// true if same, false otherwise bool EqualsScope(TypeRef a, ExportedType b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; var ra = a.ResolutionScope; var ib = b.Implementation; if (ra == ib) return true; if (ra == null || ib == null) return false; if (!recursionCounter.Increment()) return false; bool result; TypeRef ea; ExportedType eb; IModule ma; FileDef fb; AssemblyRef aa, ab; bool checkResolve = true; // If one is a nested type, the other one must be too if ((ea = ra as TypeRef) != null | (eb = ib as ExportedType) != null) { result = Equals(ea, eb); checkResolve = false; } else if (DontCompareTypeScope) result = true; else if ((ma = ra as IModule) != null & (fb = ib as FileDef) != null) result = Equals(a, ma, b, fb); else if ((aa = ra as AssemblyRef) != null & (ab = ib as AssemblyRef) != null) result = Equals(aa, a, ab, b); else if (ma != null && ab != null) result = Equals(a.DefinitionAssembly, ab, b); else if (fb != null && aa != null) result = Equals(b.DefinitionAssembly, aa, a); else { checkResolve = false; result = false; } if (!result && checkResolve && !DontCheckTypeEquivalence) { var td1 = a.Resolve(); var td2 = b.Resolve(); if (td1 != null && td2 != null) result = TypeDefScopeEquals(td1, td2); } recursionCounter.Decrement(); return result; } /// /// Compares files /// /// File #1 /// File #2 /// true if same, false otherwise bool Equals(FileDef a, FileDef b) { if (a == b) return true; if (a == null || b == null) return false; return UTF8String.CaseInsensitiveEquals(a.Name, b.Name); } /// /// Compares a module with a file /// /// Module /// File /// true if same, false otherwise bool Equals(IModule a, FileDef b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; //TODO: You should compare against the module's file name, not the name in the metadata! return UTF8String.CaseInsensitiveEquals(a.Name, b.Name); } /// /// Compares modules /// /// Module #1 /// Module #2 /// true if same, false otherwise internal bool Equals(IModule a, IModule b) { if (a == b) return true; if (a == null || b == null) return false; if (!MscorlibIsNotSpecial && IsCorLib(a) && IsCorLib(b)) return true; return UTF8String.CaseInsensitiveEquals(a.Name, b.Name); } static bool IsCorLib(ModuleDef a) { return a != null && a.IsManifestModule && a.Assembly.IsCorLib(); } static bool IsCorLib(IModule a) { var mod = a as ModuleDef; return mod != null && mod.IsManifestModule && mod.Assembly.IsCorLib(); } static bool IsCorLib(Module a) { return a != null && a.Assembly.ManifestModule == a && a.Assembly == typeof(void).Assembly; } static bool IsCorLib(IAssembly a) { return a.IsCorLib(); } static bool IsCorLib(Assembly a) { return a == typeof(void).Assembly; } /// /// Compares modules /// /// Module #1 /// Module #2 /// true if same, false otherwise bool Equals(ModuleDef a, ModuleDef b) { if (a == b) return true; if (a == null || b == null) return false; if (!MscorlibIsNotSpecial && IsCorLib(a) && IsCorLib(b)) return true; if (!recursionCounter.Increment()) return false; bool result = Equals((IModule)a, (IModule)b) && Equals(a.Assembly, b.Assembly); recursionCounter.Decrement(); return result; } /// /// Compares assemblies /// /// Assembly #1 /// Assembly #2 /// true if same, false otherwise bool Equals(IAssembly a, IAssembly b) { if (a == b) return true; if (a == null || b == null) return false; if (!MscorlibIsNotSpecial && IsCorLib(a) && IsCorLib(b)) return true; if (!recursionCounter.Increment()) return false; bool result = UTF8String.CaseInsensitiveEquals(a.Name, b.Name) && (!CompareAssemblyPublicKeyToken || PublicKeyBase.TokenEquals(a.PublicKeyOrToken, b.PublicKeyOrToken)) && (!CompareAssemblyVersion || Utils.Equals(a.Version, b.Version)) && (!CompareAssemblyLocale || Utils.LocaleEquals(a.Culture, b.Culture)); recursionCounter.Decrement(); return result; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeSig a, TypeSig b) { if (IgnoreModifiers) { a = a.RemoveModifiers(); b = b.RemoveModifiers(); } if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; } if (a.ElementType != b.ElementType) { // Signatures must be identical. It's possible to have a U4 in a sig (short form // of System.UInt32), or a ValueType + System.UInt32 TypeRef (long form), but these // should not match in a sig (also the long form is invalid). result = false; } else { switch (a.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: case ElementType.Sentinel: result = true; break; case ElementType.Ptr: case ElementType.ByRef: case ElementType.SZArray: case ElementType.Pinned: result = Equals(a.Next, b.Next); break; case ElementType.Array: ArraySig ara = a as ArraySig, arb = b as ArraySig; result = ara.Rank == arb.Rank && Equals(ara.Sizes, arb.Sizes) && Equals(ara.LowerBounds, arb.LowerBounds) && Equals(a.Next, b.Next); break; case ElementType.ValueType: case ElementType.Class: if (RawSignatureCompare) result = TokenEquals((a as ClassOrValueTypeSig).TypeDefOrRef, (b as ClassOrValueTypeSig).TypeDefOrRef); else result = Equals((IType)(a as ClassOrValueTypeSig).TypeDefOrRef, (IType)(b as ClassOrValueTypeSig).TypeDefOrRef); break; case ElementType.Var: case ElementType.MVar: result = (a as GenericSig).Number == (b as GenericSig).Number; break; case ElementType.GenericInst: var gia = (GenericInstSig)a; var gib = (GenericInstSig)b; if (RawSignatureCompare) { var gt1 = gia.GenericType; var gt2 = gib.GenericType; result = TokenEquals(gt1 == null ? null : gt1.TypeDefOrRef, gt2 == null ? null : gt2.TypeDefOrRef) && Equals(gia.GenericArguments, gib.GenericArguments); } else { result = Equals(gia.GenericType, gib.GenericType) && Equals(gia.GenericArguments, gib.GenericArguments); } break; case ElementType.FnPtr: result = Equals((a as FnPtrSig).Signature, (b as FnPtrSig).Signature); break; case ElementType.CModReqd: case ElementType.CModOpt: if (RawSignatureCompare) result = TokenEquals((a as ModifierSig).Modifier, (b as ModifierSig).Modifier) && Equals(a.Next, b.Next); else result = Equals((IType)(a as ModifierSig).Modifier, (IType)(b as ModifierSig).Modifier) && Equals(a.Next, b.Next); break; case ElementType.ValueArray: result = (a as ValueArraySig).Size == (b as ValueArraySig).Size && Equals(a.Next, b.Next); break; case ElementType.Module: result = (a as ModuleSig).Index == (b as ModuleSig).Index && Equals(a.Next, b.Next); break; case ElementType.End: case ElementType.R: case ElementType.Internal: default: result = false; break; } } recursionCounter.Decrement(); return result; } static bool TokenEquals(ITypeDefOrRef a, ITypeDefOrRef b) { if (a == b) return true; if (a == null || b == null) return false; return a.MDToken == b.MDToken; } /// /// Gets the hash code of a type /// /// The type /// The hash code public int GetHashCode(TypeSig a) { // ******************************************** // IMPORTANT: This must match GetHashCode(Type) // ******************************************** if (a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash; if (genericArguments != null) a = genericArguments.Resolve(a); switch (a.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: case ElementType.ValueType: case ElementType.Class: // When comparing an ExportedType/TypeDef/TypeRef to a TypeDefOrRefSig/Class/ValueType, // the ET is ignored, so we must ignore it when calculating the hash. hash = GetHashCode((IType)(a as TypeDefOrRefSig).TypeDefOrRef); break; case ElementType.Sentinel: hash = HASHCODE_MAGIC_ET_SENTINEL; break; case ElementType.Ptr: hash = HASHCODE_MAGIC_ET_PTR + GetHashCode(a.Next); break; case ElementType.ByRef: hash = HASHCODE_MAGIC_ET_BYREF + GetHashCode(a.Next); break; case ElementType.SZArray: hash = HASHCODE_MAGIC_ET_SZARRAY + GetHashCode(a.Next); break; case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Pinned: // When comparing an ExportedType/TypeDef/TypeRef to a ModifierSig/PinnedSig, // the ET is ignored, so we must ignore it when calculating the hash. hash = GetHashCode(a.Next); break; case ElementType.Array: // Don't include sizes and lower bounds since GetHashCode(Type) doesn't (and can't). ArraySig ara = (ArraySig)a; hash = HASHCODE_MAGIC_ET_ARRAY + (int)ara.Rank + GetHashCode(ara.Next); break; case ElementType.Var: hash = HASHCODE_MAGIC_ET_VAR + (int)(a as GenericVar).Number; break; case ElementType.MVar: hash = HASHCODE_MAGIC_ET_MVAR + (int)(a as GenericMVar).Number; break; case ElementType.GenericInst: var gia = (GenericInstSig)a; hash = HASHCODE_MAGIC_ET_GENERICINST; if (SubstituteGenericParameters) { InitializeGenericArguments(); genericArguments.PushTypeArgs(gia.GenericArguments); hash += GetHashCode(gia.GenericType); genericArguments.PopTypeArgs(); } else hash += GetHashCode(gia.GenericType); hash += GetHashCode(gia.GenericArguments); break; case ElementType.FnPtr: hash = GetHashCode_FnPtr_SystemIntPtr(); break; case ElementType.ValueArray: hash = HASHCODE_MAGIC_ET_VALUEARRAY + (int)(a as ValueArraySig).Size + GetHashCode(a.Next); break; case ElementType.Module: hash = HASHCODE_MAGIC_ET_MODULE + (int)(a as ModuleSig).Index + GetHashCode(a.Next); break; case ElementType.End: case ElementType.R: case ElementType.Internal: default: hash = 0; break; } recursionCounter.Decrement(); return hash; } /// /// Compares type lists /// /// Type list #1 /// Type list #2 /// true if same, false otherwise public bool Equals(IList a, IList b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; if (a.Count != b.Count) result = false; else { int i; for (i = 0; i < a.Count; i++) { if (!Equals(a[i], b[i])) break; } result = i == a.Count; } recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a type list /// /// The type list /// The hash code public int GetHashCode(IList a) { //************************************************************************ // IMPORTANT: This code must match any other GetHashCode(IList) //************************************************************************ if (a == null) return 0; if (!recursionCounter.Increment()) return 0; uint hash = 0; for (int i = 0; i < a.Count; i++) { hash += (uint)GetHashCode(a[i]); hash = (hash << 13) | (hash >> 19); } recursionCounter.Decrement(); return (int)hash; } bool Equals(IList a, IList b) { if (a == b) return true; if (a == null || b == null) return false; if (a.Count != b.Count) return false; for (int i = 0; i < a.Count; i++) { if (a[i] != b[i]) return false; } return true; } bool Equals(IList a, IList b) { if (a == b) return true; if (a == null || b == null) return false; if (a.Count != b.Count) return false; for (int i = 0; i < a.Count; i++) { if (a[i] != b[i]) return false; } return true; } /// /// Compares signatures /// /// Sig #1 /// Sig #2 /// true if same, false otherwise public bool Equals(CallingConventionSig a, CallingConventionSig b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; if (a.GetCallingConvention() != b.GetCallingConvention()) result = false; else { switch (a.GetCallingConvention() & CallingConvention.Mask) { case CallingConvention.Default: case CallingConvention.C: case CallingConvention.StdCall: case CallingConvention.ThisCall: case CallingConvention.FastCall: case CallingConvention.VarArg: case CallingConvention.Property: case CallingConvention.NativeVarArg: MethodBaseSig ma = a as MethodBaseSig, mb = b as MethodBaseSig; result = ma != null && mb != null && Equals(ma, mb); break; case CallingConvention.Field: FieldSig fa = a as FieldSig, fb = b as FieldSig; result = fa != null && fb != null && Equals(fa, fb); break; case CallingConvention.LocalSig: LocalSig la = a as LocalSig, lb = b as LocalSig; result = la != null && lb != null && Equals(la, lb); break; case CallingConvention.GenericInst: GenericInstMethodSig ga = a as GenericInstMethodSig, gb = b as GenericInstMethodSig; result = ga != null && gb != null && Equals(ga, gb); break; case CallingConvention.Unmanaged: default: result = false; break; } } recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a sig /// /// The sig /// The hash code public int GetHashCode(CallingConventionSig a) { if (a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash; switch (a.GetCallingConvention() & CallingConvention.Mask) { case CallingConvention.Default: case CallingConvention.C: case CallingConvention.StdCall: case CallingConvention.ThisCall: case CallingConvention.FastCall: case CallingConvention.VarArg: case CallingConvention.Property: case CallingConvention.NativeVarArg: MethodBaseSig ma = a as MethodBaseSig; hash = ma == null ? 0 : GetHashCode(ma); break; case CallingConvention.Field: FieldSig fa = a as FieldSig; hash = fa == null ? 0 : GetHashCode(fa); break; case CallingConvention.LocalSig: LocalSig la = a as LocalSig; hash = la == null ? 0 : GetHashCode(la); break; case CallingConvention.GenericInst: GenericInstMethodSig ga = a as GenericInstMethodSig; hash = ga == null ? 0 : GetHashCode(ga); break; case CallingConvention.Unmanaged: default: hash = GetHashCode_CallingConvention(a); break; } recursionCounter.Decrement(); return hash; } /// /// Compares method/property sigs /// /// Method/property #1 /// Method/property #2 /// true if same, false otherwise public bool Equals(MethodBaseSig a, MethodBaseSig b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result = a.GetCallingConvention() == b.GetCallingConvention() && (DontCompareReturnType || Equals(a.RetType, b.RetType)) && Equals(a.Params, b.Params) && (!a.Generic || a.GenParamCount == b.GenParamCount) && (!CompareSentinelParams || Equals(a.ParamsAfterSentinel, b.ParamsAfterSentinel)); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a method/property sig /// /// The method/property sig /// The hash code public int GetHashCode(MethodBaseSig a) { if (a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash; hash = GetHashCode_CallingConvention(a) + GetHashCode(a.Params); if (!DontCompareReturnType) hash += GetHashCode(a.RetType); if (a.Generic) hash += GetHashCode_ElementType_MVar((int)a.GenParamCount); if (CompareSentinelParams) hash += GetHashCode(a.ParamsAfterSentinel); recursionCounter.Decrement(); return hash; } int GetHashCode_CallingConvention(CallingConventionSig a) { return GetHashCode(a.GetCallingConvention()); } int GetHashCode(CallingConvention a) { //******************************************************************* // IMPORTANT: This hash must match the Reflection call conv hash code //******************************************************************* switch (a & CallingConvention.Mask) { case CallingConvention.Default: case CallingConvention.C: case CallingConvention.StdCall: case CallingConvention.ThisCall: case CallingConvention.FastCall: case CallingConvention.VarArg: case CallingConvention.Property: case CallingConvention.GenericInst: case CallingConvention.Unmanaged: case CallingConvention.NativeVarArg: case CallingConvention.Field: return (int)(a & (CallingConvention.Generic | CallingConvention.HasThis | CallingConvention.ExplicitThis)); case CallingConvention.LocalSig: default: return (int)a; } } /// /// Compares field sigs /// /// Field sig #1 /// Field sig #2 /// true if same, false otherwise public bool Equals(FieldSig a, FieldSig b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result = a.GetCallingConvention() == b.GetCallingConvention() && Equals(a.Type, b.Type); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a field sig /// /// The field sig /// The hash code public int GetHashCode(FieldSig a) { if (a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash; hash = GetHashCode_CallingConvention(a) + GetHashCode(a.Type); recursionCounter.Decrement(); return hash; } /// /// Compares local sigs /// /// Local sig #1 /// Local sig #2 /// true if same, false otherwise public bool Equals(LocalSig a, LocalSig b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result = a.GetCallingConvention() == b.GetCallingConvention() && Equals(a.Locals, b.Locals); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a local sig /// /// The local sig /// The hash code public int GetHashCode(LocalSig a) { if (a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash; hash = GetHashCode_CallingConvention(a) + GetHashCode(a.Locals); recursionCounter.Decrement(); return hash; } /// /// Compares generic method instance sigs /// /// Generic inst method #1 /// Generic inst method #2 /// true if same, false otherwise public bool Equals(GenericInstMethodSig a, GenericInstMethodSig b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result = a.GetCallingConvention() == b.GetCallingConvention() && Equals(a.GenericArguments, b.GenericArguments); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a generic instance method sig /// /// The generic inst method sig /// The hash code public int GetHashCode(GenericInstMethodSig a) { if (a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash; hash = GetHashCode_CallingConvention(a) + GetHashCode(a.GenericArguments); recursionCounter.Decrement(); return hash; } /// /// Compares methods /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(IMethod a, IMethod b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; MethodDef mda, mdb; MemberRef mra, mrb; MethodSpec msa, msb; if ((mda = a as MethodDef) != null & (mdb = b as MethodDef) != null) result = Equals(mda, mdb); else if ((mra = a as MemberRef) != null & (mrb = b as MemberRef) != null) result = Equals(mra, mrb); else if ((msa = a as MethodSpec) != null && (msb = b as MethodSpec) != null) result = Equals(msa, msb); else if (mda != null && mrb != null) result = Equals(mda, mrb); else if (mra != null && mdb != null) result = Equals(mdb, mra); else result = false; recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a method /// /// The method /// The hash code public int GetHashCode(IMethod a) { if (a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash; MethodDef mda; MemberRef mra; MethodSpec msa; if ((mda = a as MethodDef) != null) hash = GetHashCode(mda); else if ((mra = a as MemberRef) != null) hash = GetHashCode(mra); else if ((msa = a as MethodSpec) != null) hash = GetHashCode(msa); else hash = 0; recursionCounter.Decrement(); return hash; } /// /// Compares methods /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(MemberRef a, MethodDef b) { return Equals(b, a); } /// /// Compares methods /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(MethodDef a, MemberRef b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; if (!DontProjectWinMDRefs) { var mra = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; if (mra != null) { result = Equals(mra, b); goto exit; } } result = (PrivateScopeMethodIsComparable || !a.IsPrivateScope) && Equals_MethodFieldNames(a.Name, b.Name) && Equals(a.Signature, b.Signature) && (!CompareMethodFieldDeclaringType || Equals(a.DeclaringType, b.Class)); exit: ; recursionCounter.Decrement(); return result; } /// /// Compares methods /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(MethodDef a, MethodDef b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; if (!DontProjectWinMDRefs) { var mra = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); var mrb = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b); if (mra != null || mrb != null) { result = Equals((IMethod)mra ?? a, (IMethod)mrb ?? b); goto exit; } } result = Equals_MethodFieldNames(a.Name, b.Name) && Equals(a.Signature, b.Signature) && (!CompareMethodFieldDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); exit: ; recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a method /// /// The method /// The hash code public int GetHashCode(MethodDef a) { // *********************************************************************** // IMPORTANT: This hash code must match the MemberRef/MethodBase hash code // *********************************************************************** if (a == null) return 0; if (!DontProjectWinMDRefs) { var mra = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); if (mra != null) return GetHashCode(mra); } if (!recursionCounter.Increment()) return 0; int hash = GetHashCode_MethodFieldName(a.Name) + GetHashCode(a.Signature); if (CompareMethodFieldDeclaringType) hash += GetHashCode(a.DeclaringType); recursionCounter.Decrement(); return hash; } /// /// Compares MemberRefs /// /// MemberRef #1 /// MemberRef #2 /// true if same, false otherwise public bool Equals(MemberRef a, MemberRef b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; if (!DontProjectWinMDRefs) { a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; b = WinMDHelpers.ToCLR(b.Module ?? sourceModule, b) ?? b; } bool result = Equals_MethodFieldNames(a.Name, b.Name) && Equals(a.Signature, b.Signature) && (!CompareMethodFieldDeclaringType || Equals(a.Class, b.Class)); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a MemberRef /// /// The MemberRef /// The hash code public int GetHashCode(MemberRef a) { // ******************************************************************************** // IMPORTANT: This hash code must match the MethodDef/FieldDef/MethodBase hash code // ******************************************************************************** if (a == null) return 0; if (!recursionCounter.Increment()) return 0; if (!DontProjectWinMDRefs) a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; int hash = GetHashCode_MethodFieldName(a.Name); GenericInstSig git; if (SubstituteGenericParameters && (git = GetGenericInstanceType(a.Class)) != null) { InitializeGenericArguments(); genericArguments.PushTypeArgs(git.GenericArguments); hash += GetHashCode(a.Signature); genericArguments.PopTypeArgs(); } else hash += GetHashCode(a.Signature); if (CompareMethodFieldDeclaringType) hash += GetHashCode(a.Class); recursionCounter.Decrement(); return hash; } /// /// Compares MethodSpecs /// /// MethodSpec #1 /// MethodSpec #2 /// true if same, false otherwise public bool Equals(MethodSpec a, MethodSpec b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result = Equals(a.Method, b.Method) && Equals(a.Instantiation, b.Instantiation); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a MethodSpec /// /// The MethodSpec /// The hash code public int GetHashCode(MethodSpec a) { // ************************************************************* // IMPORTANT: This hash code must match the MethodBase hash code // ************************************************************* if (a == null) return 0; if (!recursionCounter.Increment()) return 0; // We must do this or it won't get the same hash code as some MethodInfos var oldOptions = SetOptions(SigComparerOptions.SubstituteGenericParameters); var gim = a.GenericInstMethodSig; if (gim != null) { InitializeGenericArguments(); genericArguments.PushMethodArgs(gim.GenericArguments); } int hash = GetHashCode(a.Method); if (gim != null) genericArguments.PopMethodArgs(); RestoreOptions(oldOptions); recursionCounter.Decrement(); return hash; } /// /// Compares MemberRefParents /// /// MemberRefParent #1 /// MemberRefParent #2 /// true if same, false otherwise bool Equals(IMemberRefParent a, IMemberRefParent b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; ITypeDefOrRef ita, itb; ModuleRef moda, modb; MethodDef ma, mb; TypeDef td; if ((ita = a as ITypeDefOrRef) != null && (itb = b as ITypeDefOrRef) != null) result = Equals((IType)ita, (IType)itb); else if ((moda = a as ModuleRef) != null & (modb = b as ModuleRef) != null) { ModuleDef omoda = moda.Module, omodb = modb.Module; result = Equals((IModule)moda, (IModule)modb) && Equals(omoda == null ? null : omoda.Assembly, omodb == null ? null : omodb.Assembly); } else if ((ma = a as MethodDef) != null && (mb = b as MethodDef) != null) result = Equals(ma, mb); else if (modb != null && (td = a as TypeDef) != null) result = EqualsGlobal(td, modb); else if (moda != null && (td = b as TypeDef) != null) result = EqualsGlobal(td, moda); else result = false; recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a MemberRefParent /// /// The MemberRefParent /// The hash code int GetHashCode(IMemberRefParent a) { if (a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash; ITypeDefOrRef ita; MethodDef ma; if ((ita = a as ITypeDefOrRef) != null) hash = GetHashCode((IType)ita); else if (a is ModuleRef) hash = GetHashCodeGlobalType(); else if ((ma = a as MethodDef) != null) { // Only use the declaring type so we get the same hash code when hashing a MethodBase. hash = GetHashCode(ma.DeclaringType); } else hash = 0; recursionCounter.Decrement(); return hash; } /// /// Compares fields /// /// Field #1 /// Field #2 /// true if same, false otherwise public bool Equals(IField a, IField b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; FieldDef fa, fb; MemberRef ma, mb; if ((fa = a as FieldDef) != null & (fb = b as FieldDef) != null) result = Equals(fa, fb); else if ((ma = a as MemberRef) != null & (mb = b as MemberRef) != null) result = Equals(ma, mb); else if (fa != null && mb != null) result = Equals(fa, mb); else if (fb != null && ma != null) result = Equals(fb, ma); else result = false; recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a field /// /// The field /// The hash code public int GetHashCode(IField a) { if (a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash; FieldDef fa; MemberRef ma; if ((fa = a as FieldDef) != null) hash = GetHashCode(fa); else if ((ma = a as MemberRef) != null) hash = GetHashCode(ma); else hash = 0; recursionCounter.Decrement(); return hash; } /// /// Compares fields /// /// Field #1 /// Field #2 /// true if same, false otherwise public bool Equals(MemberRef a, FieldDef b) { return Equals(b, a); } /// /// Compares fields /// /// Field #1 /// Field #2 /// true if same, false otherwise public bool Equals(FieldDef a, MemberRef b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result = (PrivateScopeFieldIsComparable || !a.IsPrivateScope) && Equals_MethodFieldNames(a.Name, b.Name) && Equals(a.Signature, b.Signature) && (!CompareMethodFieldDeclaringType || Equals(a.DeclaringType, b.Class)); recursionCounter.Decrement(); return result; } /// /// Compares fields /// /// Field #1 /// Field #2 /// true if same, false otherwise public bool Equals(FieldDef a, FieldDef b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result = Equals_MethodFieldNames(a.Name, b.Name) && Equals(a.Signature, b.Signature) && (!CompareMethodFieldDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a field /// /// The field /// The hash code public int GetHashCode(FieldDef a) { // ********************************************************************** // IMPORTANT: This hash code must match the MemberRef/FieldInfo hash code // ********************************************************************** if (a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash = GetHashCode_MethodFieldName(a.Name) + GetHashCode(a.Signature); if (CompareMethodFieldDeclaringType) hash += GetHashCode(a.DeclaringType); recursionCounter.Decrement(); return hash; } /// /// Compares properties /// /// Property #1 /// Property #2 /// true if same, false otherwise public bool Equals(PropertyDef a, PropertyDef b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result = Equals_PropertyNames(a.Name, b.Name) && Equals(a.Type, b.Type) && (!ComparePropertyDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a property /// /// The property /// The hash code public int GetHashCode(PropertyDef a) { // *************************************************************** // IMPORTANT: This hash code must match the PropertyInfo hash code // *************************************************************** if (a == null) return 0; if (!recursionCounter.Increment()) return 0; var sig = a.PropertySig; int hash = GetHashCode_PropertyName(a.Name) + GetHashCode(sig == null ? null : sig.RetType); if (ComparePropertyDeclaringType) hash += GetHashCode(a.DeclaringType); recursionCounter.Decrement(); return hash; } /// /// Compares events /// /// Event #1 /// Event #2 /// true if same, false otherwise public bool Equals(EventDef a, EventDef b) { if (a == b) return true; if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result = Equals_EventNames(a.Name, b.Name) && Equals((IType)a.EventType, (IType)b.EventType) && (!CompareEventDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of an event /// /// The event /// The hash code public int GetHashCode(EventDef a) { // ************************************************************ // IMPORTANT: This hash code must match the EventInfo hash code // ************************************************************ if (a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash = GetHashCode_EventName(a.Name) + GetHashCode((IType)a.EventType); if (CompareEventDeclaringType) hash += GetHashCode(a.DeclaringType); recursionCounter.Decrement(); return hash; } // Compares a with b, and a must be the global type bool EqualsGlobal(TypeDef a, ModuleRef b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result = a.IsGlobalModuleType && Equals((IModule)a.Module, (IModule)b) && Equals(a.DefinitionAssembly, GetAssembly(b.Module)); recursionCounter.Decrement(); return result; } static AssemblyDef GetAssembly(ModuleDef module) { return module == null ? null : module.Assembly; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(Type a, IType b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(IType a, Type b) { // Global methods and fields have their DeclaringType set to null. Assume // null always means the global type. if (a == null) return false; if (!recursionCounter.Increment()) return false; bool result; TypeDef td; TypeRef tr; TypeSpec ts; TypeSig sig; ExportedType et; if ((td = a as TypeDef) != null) result = Equals(td, b); else if ((tr = a as TypeRef) != null) result = Equals(tr, b); else if ((ts = a as TypeSpec) != null) result = Equals(ts, b); else if ((sig = a as TypeSig) != null) result = Equals(sig, b); else if ((et = a as ExportedType) != null) result = Equals(et, b); else result = false; recursionCounter.Decrement(); return result; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(Type a, TypeDef b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeDef a, Type b) { // Global methods and fields have their DeclaringType set to null. Assume // null always means the global type. if (a == null) return false; if ((object)b == null) return a.IsGlobalModuleType; if (!recursionCounter.Increment()) return false; bool result; if (!DontProjectWinMDRefs) { var tra = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); if (tra != null) { result = Equals(tra, b); goto exit; } } result = !b.HasElementType && Equals_TypeNames(a.Name, b.Name) && Equals_TypeNamespaces(a.Namespace, b) && EnclosingTypeEquals(a.DeclaringType, b.DeclaringType) && (DontCompareTypeScope || Equals(a.Module, b.Module)); exit: ; recursionCounter.Decrement(); return result; } bool EnclosingTypeEquals(TypeDef a, Type b) { // b == null doesn't mean that b is the global type if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; return Equals(a, b); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(Type a, TypeRef b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeRef a, Type b) { // Global methods and fields have their DeclaringType set to null. Assume // null always means the global type. if (a == null) return false; if ((object)b == null) return false; // Must use a ModuleRef to reference the global type, so always fail if (!recursionCounter.Increment()) return false; bool result; TypeRef dta; IModule aMod; AssemblyRef aAsm; if (!DontProjectWinMDRefs) a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; var scope = a.ResolutionScope; if (!b.IsTypeDef()) result = false; else if (!Equals_TypeNames(a.Name, b.Name) || !Equals_TypeNamespaces(a.Namespace, b)) result = false; else if ((dta = scope as TypeRef) != null) // nested type result = Equals(dta, b.DeclaringType); // Compare enclosing types else if (b.IsNested) result = false; // b is nested, a isn't else if (DontCompareTypeScope) result = true; else if ((aMod = scope as IModule) != null) // 'a' is defined in the same assembly as 'b' result = Equals(b, aMod, a); else if ((aAsm = scope as AssemblyRef) != null) result = Equals(b.Assembly, aAsm, a); else { result = false; //TODO: Handle the case where scope == null } recursionCounter.Decrement(); return result; } bool Equals_TypeNamespaces(UTF8String a, Type b) { if (b.IsNested) return true; return Equals_TypeNamespaces(a, b.Namespace); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(Type a, TypeSpec b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeSpec a, Type b) { // Global methods and fields have their DeclaringType set to null. Assume // null always means the global type. if (a == null) return false; if ((object)b == null) return false; // Must use a ModuleRef to reference the global type, so always fail return Equals(a.TypeSig, b); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(Type a, TypeSig b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(TypeSig a, Type b) { return Equals(a, b, false); } bool Equals(ITypeDefOrRef a, Type b, bool treatAsGenericInst) { var ts = a as TypeSpec; if (ts != null) return Equals(ts.TypeSig, b, treatAsGenericInst); return Equals(a, b); } /// /// Checks whether it's FnPtr&, FnPtr*, FnPtr[], or FnPtr[...] /// /// The type static bool IsFnPtrElementType(Type a) { if ((object)a == null || !a.HasElementType) return false; var et = a.GetElementType(); if (et == null || et.HasElementType) return false; if (et != typeof(IntPtr)) // FnPtr is mapped to System.IntPtr return false; if (!a.FullName.StartsWith("(fnptr)")) return false; return true; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if we should treat /// as a generic instance type /// true if same, false otherwise bool Equals(TypeSig a, Type b, bool treatAsGenericInst) { // Global methods and fields have their DeclaringType set to null. Assume // null always means the global type. if (a == null) return false; if ((object)b == null) return false; // Must use a ModuleRef to reference the global type, so always fail if (!recursionCounter.Increment()) return false; bool result; if (genericArguments != null) a = genericArguments.Resolve(a); switch (a.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: result = Equals(((TypeDefOrRefSig)a).TypeDefOrRef, b, treatAsGenericInst); break; case ElementType.Ptr: if (!b.IsPointer) result = false; else if (IsFnPtrElementType(b)) { a = a.Next.RemoveModifiers(); result = a != null && a.ElementType == ElementType.FnPtr; } else result = Equals(a.Next, b.GetElementType()); break; case ElementType.ByRef: if (!b.IsByRef) result = false; else if (IsFnPtrElementType(b)) { a = a.Next.RemoveModifiers(); result = a != null && a.ElementType == ElementType.FnPtr; } else result = Equals(a.Next, b.GetElementType()); break; case ElementType.SZArray: if (!b.IsArray || !b.IsSZArray()) result = false; else if (IsFnPtrElementType(b)) { a = a.Next.RemoveModifiers(); result = a != null && a.ElementType == ElementType.FnPtr; } else result = Equals(a.Next, b.GetElementType()); break; case ElementType.Pinned: result = Equals(a.Next, b, treatAsGenericInst); break; case ElementType.Array: if (!b.IsArray || b.IsSZArray()) result = false; else { ArraySig ara = a as ArraySig; result = ara.Rank == b.GetArrayRank() && (IsFnPtrElementType(b) ? (a = a.Next.RemoveModifiers()) != null && a.ElementType == ElementType.FnPtr : Equals(a.Next, b.GetElementType())); } break; case ElementType.ValueType: case ElementType.Class: result = Equals((a as ClassOrValueTypeSig).TypeDefOrRef, b, treatAsGenericInst); break; case ElementType.Var: result = b.IsGenericParameter && b.GenericParameterPosition == (a as GenericSig).Number && (object)b.DeclaringMethod == null; break; case ElementType.MVar: result = b.IsGenericParameter && b.GenericParameterPosition == (a as GenericSig).Number && (object)b.DeclaringMethod != null; break; case ElementType.GenericInst: if (!(b.IsGenericType && !b.IsGenericTypeDefinition) && !treatAsGenericInst) { result = false; break; } var gia = (GenericInstSig)a; if (SubstituteGenericParameters) { InitializeGenericArguments(); genericArguments.PushTypeArgs(gia.GenericArguments); result = Equals(gia.GenericType, b.GetGenericTypeDefinition()); genericArguments.PopTypeArgs(); } else result = Equals(gia.GenericType, b.GetGenericTypeDefinition()); result = result && Equals(gia.GenericArguments, b.GetGenericArguments()); break; case ElementType.CModReqd: case ElementType.CModOpt: result = Equals(a.Next, b, treatAsGenericInst); break; case ElementType.FnPtr: // At least in method sigs, this will be mapped to System.IntPtr result = b == typeof(IntPtr); break; case ElementType.Sentinel: case ElementType.ValueArray: case ElementType.Module: case ElementType.End: case ElementType.R: case ElementType.Internal: default: result = false; break; } recursionCounter.Decrement(); return result; } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(Type a, ExportedType b) { return Equals(b, a); } /// /// Compares types /// /// Type #1 /// Type #2 /// true if same, false otherwise public bool Equals(ExportedType a, Type b) { // Global methods and fields have their DeclaringType set to null. Assume // null always means the global type. if (a == null) return false; if ((object)b == null) return false; // Must use a ModuleRef to reference the global type, so always fail if (!recursionCounter.Increment()) return false; bool result; ExportedType dta; FileDef aFile; AssemblyRef aAsm; if (!DontProjectWinMDRefs) a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; var scope = a.Implementation; if (!b.IsTypeDef()) result = false; else if (!Equals_TypeNames(a.TypeName, b.Name) || !Equals_TypeNamespaces(a.TypeNamespace, b)) result = false; else if ((dta = scope as ExportedType) != null) // nested type result = Equals(dta, b.DeclaringType); // Compare enclosing types else if (b.IsNested) result = false; // b is nested, a isn't else if (DontCompareTypeScope) result = true; else if ((aFile = scope as FileDef) != null) result = Equals(b, aFile, a); else if ((aAsm = scope as AssemblyRef) != null) result = Equals(b.Assembly, aAsm, a); else result = false; recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a type /// /// The type /// The hash code public int GetHashCode(Type a) { return GetHashCode(a, false); } /// /// Gets the hash code of a type /// /// The type /// true if we should treat /// as a generic instance type /// The hash code public int GetHashCode(Type a, bool treatAsGenericInst) { // ************************************************************************** // IMPORTANT: This hash code must match the TypeSig/TypeDef/TypeRef hash code // ************************************************************************** if ((object)a == null) // Could be global type return GetHashCode_TypeDef(a); if (!recursionCounter.Increment()) return 0; int hash; switch (treatAsGenericInst ? ElementType.GenericInst : a.GetElementType2()) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: case ElementType.ValueType: case ElementType.Class: hash = GetHashCode_TypeDef(a); break; case ElementType.FnPtr: hash = GetHashCode_FnPtr_SystemIntPtr(); break; case ElementType.Sentinel: hash = HASHCODE_MAGIC_ET_SENTINEL; break; case ElementType.Ptr: hash = HASHCODE_MAGIC_ET_PTR + (IsFnPtrElementType(a) ? GetHashCode_FnPtr_SystemIntPtr() : GetHashCode(a.GetElementType())); break; case ElementType.ByRef: hash = HASHCODE_MAGIC_ET_BYREF + (IsFnPtrElementType(a) ? GetHashCode_FnPtr_SystemIntPtr() : GetHashCode(a.GetElementType())); break; case ElementType.SZArray: hash = HASHCODE_MAGIC_ET_SZARRAY + (IsFnPtrElementType(a) ? GetHashCode_FnPtr_SystemIntPtr() : GetHashCode(a.GetElementType())); break; case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Pinned: hash = GetHashCode(a.GetElementType()); break; case ElementType.Array: // The type doesn't store sizes and lower bounds, so can't use them to // create the hash hash = HASHCODE_MAGIC_ET_ARRAY + a.GetArrayRank() + (IsFnPtrElementType(a) ? GetHashCode_FnPtr_SystemIntPtr() : GetHashCode(a.GetElementType())); break; case ElementType.Var: hash = HASHCODE_MAGIC_ET_VAR + a.GenericParameterPosition; break; case ElementType.MVar: hash = HASHCODE_MAGIC_ET_MVAR + a.GenericParameterPosition; break; case ElementType.GenericInst: hash = HASHCODE_MAGIC_ET_GENERICINST + GetHashCode(a.GetGenericTypeDefinition()) + GetHashCode(a.GetGenericArguments()); break; case ElementType.ValueArray: case ElementType.Module: case ElementType.End: case ElementType.R: case ElementType.Internal: default: hash = 0; break; } recursionCounter.Decrement(); return hash; } /// /// Gets the hash code of a type list /// /// The type list /// The hash code int GetHashCode(IList a) { //************************************************************************ // IMPORTANT: This code must match any other GetHashCode(IList) //************************************************************************ if (a == null) return 0; if (!recursionCounter.Increment()) return 0; uint hash = 0; for (int i = 0; i < a.Count; i++) { hash += (uint)GetHashCode(a[i]); hash = (hash << 13) | (hash >> 19); } recursionCounter.Decrement(); return (int)hash; } /// /// Gets the hash code of a list with only generic method parameters () /// /// Number of generic method parameters /// Hash code static int GetHashCode_ElementType_MVar(int numGenericParams) { return GetHashCode(numGenericParams, HASHCODE_MAGIC_ET_MVAR); } static int GetHashCode(int numGenericParams, int etypeHashCode) { //************************************************************************ // IMPORTANT: This code must match any other GetHashCode(IList) //************************************************************************ uint hash = 0; for (int i = 0; i < numGenericParams; i++) { hash += (uint)(etypeHashCode + i); hash = (hash << 13) | (hash >> 19); } return (int)hash; } /// /// Gets the hash code of a TypeDef type /// /// The type /// The hash code public int GetHashCode_TypeDef(Type a) { // ************************************************************************************ // IMPORTANT: This hash code must match the Type/TypeRef/TypeDef/ExportedType // hash code and GetHashCode_FnPtr_SystemIntPtr() method // ************************************************************************************ // A global method/field's declaring type is null. This is the reason we must // return GetHashCodeGlobalType() here. if ((object)a == null) return GetHashCodeGlobalType(); int hash; hash = GetHashCode_TypeName(a.Name); if (a.IsNested) hash += HASHCODE_MAGIC_NESTED_TYPE; else hash += GetHashCode_TypeNamespace(a.Namespace); return hash; } /// /// Compares type lists /// /// Type list #1 /// Type list #2 /// true if same, false otherwise bool Equals(IList a, IList b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; if (a.Count != b.Count) result = false; else { int i; for (i = 0; i < a.Count; i++) { if (!Equals(a[i], b[i])) break; } result = i == a.Count; } recursionCounter.Decrement(); return result; } /// /// Compares modules /// /// Module #1 /// Module #2 /// true if same, false otherwise bool Equals(ModuleDef a, Module b) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; if (!MscorlibIsNotSpecial && IsCorLib(a) && IsCorLib(b)) return true; if (!recursionCounter.Increment()) return false; bool result = Equals((IModule)a, b) && Equals(a.Assembly, b.Assembly); recursionCounter.Decrement(); return result; } /// /// Compares a file and a module /// /// File /// Module /// true if same, false otherwise bool Equals(FileDef a, Module b) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; // Use b.Name since it's the filename we want to compare, not b.ScopeName return UTF8String.ToSystemStringOrEmpty(a.Name).Equals(b.Name, StringComparison.OrdinalIgnoreCase); } /// /// Compares modules /// /// Module #1 /// Module #2 /// true if same, false otherwise bool Equals(IModule a, Module b) { if ((object)a == b) return true; if (a == null || (object)b == null) return false; if (!MscorlibIsNotSpecial && IsCorLib(a) && IsCorLib(b)) return true; // Use b.ScopeName and not b.Name since b.Name is just the file name w/o path return UTF8String.ToSystemStringOrEmpty(a.Name).Equals(b.ScopeName, StringComparison.OrdinalIgnoreCase); } /// /// Compares assemblies /// /// Assembly #1 /// Assembly #2 /// true if same, false otherwise bool Equals(IAssembly a, Assembly b) { if ((object)a == b) return true; if (a == null || (object)b == null) return false; if (!MscorlibIsNotSpecial && IsCorLib(a) && IsCorLib(b)) return true; if (!recursionCounter.Increment()) return false; var bAsmName = b.GetName(); bool result = UTF8String.ToSystemStringOrEmpty(a.Name).Equals(bAsmName.Name, StringComparison.OrdinalIgnoreCase) && (!CompareAssemblyPublicKeyToken || PublicKeyBase.TokenEquals(a.PublicKeyOrToken, new PublicKeyToken(bAsmName.GetPublicKeyToken()))) && (!CompareAssemblyVersion || Utils.Equals(a.Version, bAsmName.Version)) && (!CompareAssemblyLocale || Utils.LocaleEquals(a.Culture, bAsmName.CultureInfo.Name)); recursionCounter.Decrement(); return result; } /// /// Compares method declaring types /// /// Method #1 /// Method #2 /// true if same, false otherwise bool DeclaringTypeEquals(IMethod a, MethodBase b) { // If this is disabled, always return true, even if one is null, etc. if (!CompareMethodFieldDeclaringType) return true; if ((object)a == b) return true; if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; bool result; MethodDef md; MemberRef mr; MethodSpec ms; if ((md = a as MethodDef) != null) result = DeclaringTypeEquals(md, b); else if ((mr = a as MemberRef) != null) result = DeclaringTypeEquals(mr, b); else if ((ms = a as MethodSpec) != null) result = DeclaringTypeEquals(ms, b); else result = false; recursionCounter.Decrement(); return result; } bool DeclaringTypeEquals(MethodDef a, MethodBase b) { // If this is disabled, always return true, even if one is null, etc. if (!CompareMethodFieldDeclaringType) return true; if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; return Equals(a.DeclaringType, b.DeclaringType); } bool DeclaringTypeEquals(MemberRef a, MethodBase b) { // If this is disabled, always return true, even if one is null, etc. if (!CompareMethodFieldDeclaringType) return true; if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; return Equals(a.Class, b.DeclaringType, b.Module); } bool DeclaringTypeEquals(MethodSpec a, MethodBase b) { // If this is disabled, always return true, even if one is null, etc. if (!CompareMethodFieldDeclaringType) return true; if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; return DeclaringTypeEquals(a.Method, b); } /// /// Compares methods /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(MethodBase a, IMethod b) { return Equals(b, a); } /// /// Compares methods /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(IMethod a, MethodBase b) { if ((object)a == b) return true; if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; bool result; MethodDef md; MemberRef mr; MethodSpec ms; if ((md = a as MethodDef) != null) result = Equals(md, b); else if ((mr = a as MemberRef) != null) result = Equals(mr, b); else if ((ms = a as MethodSpec) != null) result = Equals(ms, b); else result = false; recursionCounter.Decrement(); return result; } /// /// Compares methods /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(MethodBase a, MethodDef b) { return Equals(b, a); } /// /// Compares methods /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(MethodDef a, MethodBase b) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; bool result; if (!DontProjectWinMDRefs) { var mra = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a); if (mra != null) { result = Equals(mra, b); goto exit; } } var amSig = a.MethodSig; result = Equals_MethodFieldNames(a.Name, b.Name) && amSig != null && ((amSig.Generic && b.IsGenericMethodDefinition && b.IsGenericMethod) || (!amSig.Generic && !b.IsGenericMethodDefinition && !b.IsGenericMethod)) && Equals(amSig, b) && (!CompareMethodFieldDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); exit: ; recursionCounter.Decrement(); return result; } /// /// Compares method sigs /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(MethodBase a, MethodSig b) { return Equals(b, a); } /// /// Compares method sigs /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(MethodSig a, MethodBase b) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; bool result = Equals(a.GetCallingConvention(), b) && (DontCompareReturnType || ReturnTypeEquals(a.RetType, b)) && Equals(a.Params, b.GetParameters(), b.DeclaringType) && (!a.Generic || a.GenParamCount == b.GetGenericArguments().Length); recursionCounter.Decrement(); return result; } /// /// Compares methods /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(MethodBase a, MemberRef b) { return Equals(b, a); } /// /// Compares methods /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(MemberRef a, MethodBase b) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; bool result; if (!DontProjectWinMDRefs) a = WinMDHelpers.ToCLR(a.Module ?? sourceModule, a) ?? a; if (b.IsGenericMethod && !b.IsGenericMethodDefinition) { // 'a' must be a method ref in a generic type. This comparison must match // the MethodSpec vs MethodBase comparison code. result = a.IsMethodRef && a.MethodSig.Generic; var oldOptions = ClearOptions(SigComparerOptions.CompareMethodFieldDeclaringType); result = result && Equals(a, b.Module.ResolveMethod(b.MetadataToken)); RestoreOptions(oldOptions); result = result && DeclaringTypeEquals(a, b); result = result && GenericMethodArgsEquals((int)a.MethodSig.GenParamCount, b.GetGenericArguments()); } else { var amSig = a.MethodSig; result = Equals_MethodFieldNames(a.Name, b.Name) && amSig != null && ((amSig.Generic && b.IsGenericMethodDefinition && b.IsGenericMethod) || (!amSig.Generic && !b.IsGenericMethodDefinition && !b.IsGenericMethod)); GenericInstSig git; if (SubstituteGenericParameters && (git = GetGenericInstanceType(a.Class)) != null) { InitializeGenericArguments(); genericArguments.PushTypeArgs(git.GenericArguments); result = result && Equals(amSig, b); genericArguments.PopTypeArgs(); } else result = result && Equals(amSig, b); result = result && (!CompareMethodFieldDeclaringType || Equals(a.Class, b.DeclaringType, b.Module)); } recursionCounter.Decrement(); return result; } /// /// Compares generic method args, making sure only /// contains s. /// /// Number of generic method args in method #1 /// Generic method args in method #2 /// true if same, false otherwise static bool GenericMethodArgsEquals(int numMethodArgs, IList methodGenArgs) { if (numMethodArgs != methodGenArgs.Count) return false; for (int i = 0; i < numMethodArgs; i++) { if (methodGenArgs[i].GetElementType2() != ElementType.MVar) return false; } return true; } bool Equals(IMemberRefParent a, Type b, Module bModule) { // Global methods and fields have their DeclaringType set to null. Assume // null always means the global type. if (a == null) return false; if (!recursionCounter.Increment()) return false; bool result; ITypeDefOrRef ita; ModuleRef moda; MethodDef ma; TypeDef td; if ((ita = a as ITypeDefOrRef) != null) result = Equals((IType)ita, b); else if ((moda = a as ModuleRef) != null) { ModuleDef omoda = moda.Module; result = (object)b == null && // b == null => it's the global type Equals(moda, bModule) && Equals(omoda == null ? null : omoda.Assembly, bModule.Assembly); } else if ((ma = a as MethodDef) != null) result = Equals(ma.DeclaringType, b); else if ((object)b == null && (td = a as TypeDef) != null) result = td.IsGlobalModuleType; else result = false; recursionCounter.Decrement(); return result; } /// /// Compares methods /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(MethodBase a, MethodSpec b) { return Equals(b, a); } /// /// Compares methods /// /// Method #1 /// Method #2 /// true if same, false otherwise public bool Equals(MethodSpec a, MethodBase b) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; // Make sure it's a MethodSpec bool result = b.IsGenericMethod && !b.IsGenericMethodDefinition; // Don't compare declaring types yet because the resolved method has the wrong // declaring type (its declaring type is a generic type def). // NOTE: We must not push generic method args when comparing a.Method var oldOptions = ClearOptions(SigComparerOptions.CompareMethodFieldDeclaringType); result = result && Equals(a.Method, b.Module.ResolveMethod(b.MetadataToken)); RestoreOptions(oldOptions); result = result && DeclaringTypeEquals(a.Method, b); var gim = a.GenericInstMethodSig; result = result && gim != null && Equals(gim.GenericArguments, b.GetGenericArguments()); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a MethodBase /// /// The MethodBase /// The hash code public int GetHashCode(MethodBase a) { if ((object)a == null) return 0; if (!recursionCounter.Increment()) return 0; // *********************************************************************** // IMPORTANT: This hash code must match the MemberRef/MethodSpec hash code // *********************************************************************** int hash = GetHashCode_MethodFieldName(a.Name) + GetHashCode_MethodSig(a); if (CompareMethodFieldDeclaringType) hash += GetHashCode(a.DeclaringType); recursionCounter.Decrement(); return hash; } int GetHashCode_MethodSig(MethodBase a) { if ((object)a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash; hash = GetHashCode_CallingConvention(a.CallingConvention, a.IsGenericMethod) + GetHashCode(a.GetParameters(), a.DeclaringType); if (!DontCompareReturnType) hash += GetHashCode_ReturnType(a); if (a.IsGenericMethod) hash += GetHashCode_ElementType_MVar(a.GetGenericArguments().Length); recursionCounter.Decrement(); return hash; } /// /// Gets the hash code of a parameter list /// /// The type list /// Declaring type of method that owns parameter /// The hash code int GetHashCode(IList a, Type declaringType) { //************************************************************************ // IMPORTANT: This code must match any other GetHashCode(IList) //************************************************************************ if (a == null) return 0; if (!recursionCounter.Increment()) return 0; uint hash = 0; for (int i = 0; i < a.Count; i++) { hash += (uint)GetHashCode(a[i], declaringType); hash = (hash << 13) | (hash >> 19); } recursionCounter.Decrement(); return (int)hash; } int GetHashCode_ReturnType(MethodBase a) { var mi = a as MethodInfo; if ((object)mi != null) return GetHashCode(mi.ReturnParameter, a.DeclaringType); return GetHashCode(typeof(void)); } int GetHashCode(ParameterInfo a, Type declaringType) { return GetHashCode(a.ParameterType, declaringType.MustTreatTypeAsGenericInstType(a.ParameterType)); } int GetHashCode(Type a, Type declaringType) { return GetHashCode(a, declaringType.MustTreatTypeAsGenericInstType(a)); } /// /// Compares calling conventions /// /// Calling convention /// Method /// static bool Equals(CallingConvention a, MethodBase b) { var bc = b.CallingConvention; if (((a & CallingConvention.Generic) != 0) != b.IsGenericMethod) return false; if (((a & CallingConvention.HasThis) != 0) != ((bc & CallingConventions.HasThis) != 0)) return false; if (((a & CallingConvention.ExplicitThis) != 0) != ((bc & CallingConventions.ExplicitThis) != 0)) return false; var cca = a & CallingConvention.Mask; switch (bc & CallingConventions.Any) { case CallingConventions.Standard: if (cca == CallingConvention.VarArg || cca == CallingConvention.NativeVarArg) return false; break; case CallingConventions.VarArgs: if (cca != CallingConvention.VarArg && cca != CallingConvention.NativeVarArg) return false; break; case CallingConventions.Any: default: break; } return true; } static int GetHashCode_CallingConvention(CallingConventions a, bool isGeneric) { //************************************************************** // IMPORTANT: This hash must match the other call conv hash code //************************************************************** CallingConvention cc = 0; if (isGeneric) cc |= CallingConvention.Generic; if ((a & CallingConventions.HasThis) != 0) cc |= CallingConvention.HasThis; if ((a & CallingConventions.ExplicitThis) != 0) cc |= CallingConvention.ExplicitThis; return (int)cc; } /// /// Compares return types /// /// Return type #1 /// MethodBase /// true if same, false otherwise bool ReturnTypeEquals(TypeSig a, MethodBase b) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; bool result; var mi = b as MethodInfo; if ((object)mi != null) result = Equals(a, mi.ReturnParameter, b.DeclaringType); else if (b is ConstructorInfo) result = IsSystemVoid(a); else result = false; recursionCounter.Decrement(); return result; } static bool IsSystemVoid(TypeSig a) { return a.RemovePinnedAndModifiers().GetElementType() == ElementType.Void; } /// /// Compares parameter lists /// /// Type list #1 /// Type list #2 /// Declaring type of method that owns parameter /// true if same, false otherwise bool Equals(IList a, IList b, Type declaringType) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; if (a.Count != b.Count) result = false; else { int i; for (i = 0; i < a.Count; i++) { if (!Equals(a[i], b[i], declaringType)) break; } result = i == a.Count; } recursionCounter.Decrement(); return result; } /// /// Compares parameter types /// /// Parameter type #1 /// Parameter #2 /// Declaring type of method that owns parameter /// true if same, false otherwise bool Equals(TypeSig a, ParameterInfo b, Type declaringType) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; TypeSig a2; bool result = ModifiersEquals(a, b.GetRequiredCustomModifiers(), b.GetOptionalCustomModifiers(), out a2) && Equals(a2, b.ParameterType, declaringType.MustTreatTypeAsGenericInstType(b.ParameterType)); recursionCounter.Decrement(); return result; } bool ModifiersEquals(TypeSig a, IList reqMods2, IList optMods2, out TypeSig aAfterModifiers) { aAfterModifiers = a; if (!(a is ModifierSig)) return reqMods2.Count == 0 && optMods2.Count == 0; if (!recursionCounter.Increment()) return false; bool result; var reqMods1 = new List(reqMods2.Count); var optMods1 = new List(optMods2.Count); while (true) { var modifierSig = aAfterModifiers as ModifierSig; if (modifierSig == null) break; if (modifierSig is CModOptSig) optMods1.Add(modifierSig.Modifier); else reqMods1.Add(modifierSig.Modifier); // This can only loop forever if the user created a loop. It's not possible // to create a loop with invalid metadata. aAfterModifiers = aAfterModifiers.Next; } optMods1.Reverse(); reqMods1.Reverse(); result = reqMods1.Count == reqMods2.Count && optMods1.Count == optMods2.Count && ModifiersEquals(reqMods1, reqMods2) && ModifiersEquals(optMods1, optMods2); recursionCounter.Decrement(); return result; } bool ModifiersEquals(IList a, IList b) { if ((object)a == (object)b) return true; // both are null if (a == null || b == null) return false; if (!recursionCounter.Increment()) return false; bool result; if (a.Count != b.Count) result = false; else { int i; for (i = 0; i < b.Count; i++) { if (!Equals(a[i], b[i])) break; } result = i == b.Count; } recursionCounter.Decrement(); return result; } /// /// Compares fields /// /// Field #1 /// Field #2 /// true if same, false otherwise public bool Equals(FieldInfo a, IField b) { return Equals(b, a); } /// /// Compares fields /// /// Field #1 /// Field #2 /// true if same, false otherwise public bool Equals(IField a, FieldInfo b) { if ((object)a == b) return true; if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; bool result; FieldDef fa; MemberRef ma; if ((fa = a as FieldDef) != null) result = Equals(fa, b); else if ((ma = a as MemberRef) != null) result = Equals(ma, b); else result = false; recursionCounter.Decrement(); return result; } /// /// Compares fields /// /// Field #1 /// Field #2 /// true if same, false otherwise public bool Equals(FieldInfo a, FieldDef b) { return Equals(b, a); } /// /// Compares fields /// /// Field #1 /// Field #2 /// true if same, false otherwise public bool Equals(FieldDef a, FieldInfo b) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; bool result = Equals_MethodFieldNames(a.Name, b.Name) && Equals(a.FieldSig, b) && (!CompareMethodFieldDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); recursionCounter.Decrement(); return result; } bool Equals(FieldSig a, FieldInfo b) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; TypeSig a2; bool result = ModifiersEquals(a.Type, b.GetRequiredCustomModifiers(), b.GetOptionalCustomModifiers(), out a2) && Equals(a2, b.FieldType, b.DeclaringType.MustTreatTypeAsGenericInstType(b.FieldType)); recursionCounter.Decrement(); return result; } /// /// Compares fields /// /// Field #1 /// Field #2 /// true if same, false otherwise public bool Equals(FieldInfo a, MemberRef b) { return Equals(b, a); } /// /// Compares fields /// /// Field #1 /// Field #2 /// true if same, false otherwise public bool Equals(MemberRef a, FieldInfo b) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; bool result = Equals_MethodFieldNames(a.Name, b.Name); GenericInstSig git; if (SubstituteGenericParameters && (git = GetGenericInstanceType(a.Class)) != null) { InitializeGenericArguments(); genericArguments.PushTypeArgs(git.GenericArguments); result = result && Equals(a.FieldSig, b); genericArguments.PopTypeArgs(); } else result = result && Equals(a.FieldSig, b); result = result && (!CompareMethodFieldDeclaringType || Equals(a.Class, b.DeclaringType, b.Module)); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a field /// /// The field /// The hash code public int GetHashCode(FieldInfo a) { // ************************************************************ // IMPORTANT: This hash code must match the MemberRef hash code // ************************************************************ if ((object)a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash = GetHashCode_MethodFieldName(a.Name) + GetHashCode_FieldSig(a); if (CompareMethodFieldDeclaringType) hash += GetHashCode(a.DeclaringType); recursionCounter.Decrement(); return hash; } int GetHashCode_FieldSig(FieldInfo a) { if ((object)a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash; hash = GetHashCode_CallingConvention(0, false) + GetHashCode(a.FieldType, a.DeclaringType); recursionCounter.Decrement(); return hash; } /// /// Compares properties /// /// Property #1 /// Property #2 /// true if same, false otherwise public bool Equals(PropertyDef a, PropertyInfo b) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; bool result = Equals_PropertyNames(a.Name, b.Name) && Equals(a.PropertySig, b) && (!ComparePropertyDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); recursionCounter.Decrement(); return result; } bool Equals(PropertySig a, PropertyInfo b) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; TypeSig a2; bool result = ModifiersEquals(a.RetType, b.GetRequiredCustomModifiers(), b.GetOptionalCustomModifiers(), out a2) && Equals(a2, b.PropertyType, b.DeclaringType.MustTreatTypeAsGenericInstType(b.PropertyType)); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of a property /// /// The property /// The hash code public int GetHashCode(PropertyInfo a) { // ************************************************************** // IMPORTANT: This hash code must match the PropertyDef hash code // ************************************************************** if ((object)a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash = GetHashCode_PropertyName(a.Name) + GetHashCode(a.PropertyType, a.DeclaringType); if (ComparePropertyDeclaringType) hash += GetHashCode(a.DeclaringType); recursionCounter.Decrement(); return hash; } /// /// Compares events /// /// Event #1 /// Event #2 /// true if same, false otherwise public bool Equals(EventDef a, EventInfo b) { if ((object)a == (object)b) return true; // both are null if (a == null || (object)b == null) return false; if (!recursionCounter.Increment()) return false; bool result = Equals_EventNames(a.Name, b.Name) && Equals(a.EventType, b.EventHandlerType, b.DeclaringType.MustTreatTypeAsGenericInstType(b.EventHandlerType)) && (!CompareEventDeclaringType || Equals(a.DeclaringType, b.DeclaringType)); recursionCounter.Decrement(); return result; } /// /// Gets the hash code of an event /// /// The event /// The hash code public int GetHashCode(EventInfo a) { // *********************************************************** // IMPORTANT: This hash code must match the EventDef hash code // *********************************************************** if ((object)a == null) return 0; if (!recursionCounter.Increment()) return 0; int hash = GetHashCode_EventName(a.Name) + GetHashCode(a.EventHandlerType, a.DeclaringType); if (CompareEventDeclaringType) hash += GetHashCode(a.DeclaringType); recursionCounter.Decrement(); return hash; } /// public override string ToString() { return string.Format("{0} - {1}", recursionCounter, options); } } } dnlib-2.1_VS2010/src/DotNet/SignatureReader.cs000066400000000000000000000666331325033663500210020ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.IO; using dnlib.Threading; namespace dnlib.DotNet { /// /// Helps resolve types /// public interface ISignatureReaderHelper { /// /// Resolves a /// /// A TypeDefOrRef coded token /// Generic parameter context /// A or null if /// is invalid ITypeDefOrRef ResolveTypeDefOrRef(uint codedToken, GenericParamContext gpContext); /// /// Converts the address of a to a /// /// /// Address of . This is also known as the /// method table and has the same value as /// A or null if not supported TypeSig ConvertRTInternalAddress(IntPtr address); } /// /// Reads signatures from the #Blob stream /// public struct SignatureReader : IDisposable { readonly ISignatureReaderHelper helper; readonly ICorLibTypes corLibTypes; readonly IBinaryReader reader; readonly GenericParamContext gpContext; RecursionCounter recursionCounter; /// /// Reads a signature from the #Blob stream /// /// Reader module /// #Blob stream offset of signature /// A new instance or null if /// is invalid. public static CallingConventionSig ReadSig(ModuleDefMD readerModule, uint sig) { return ReadSig(readerModule, sig, new GenericParamContext()); } /// /// Reads a signature from the #Blob stream /// /// Reader module /// #Blob stream offset of signature /// Generic parameter context /// A new instance or null if /// is invalid. public static CallingConventionSig ReadSig(ModuleDefMD readerModule, uint sig, GenericParamContext gpContext) { try { using (var reader = new SignatureReader(readerModule, sig, gpContext)) { if (reader.reader.Length == 0) return null; var csig = reader.ReadSig(); if (csig != null) csig.ExtraData = reader.GetExtraData(); return csig; } } catch { return null; } } /// /// Reads a signature /// /// The module where the signature is located in /// The signature data /// A new instance or null if /// is invalid. public static CallingConventionSig ReadSig(ModuleDefMD module, byte[] signature) { return ReadSig(module, module.CorLibTypes, MemoryImageStream.Create(signature), new GenericParamContext()); } /// /// Reads a signature /// /// The module where the signature is located in /// The signature data /// Generic parameter context /// A new instance or null if /// is invalid. public static CallingConventionSig ReadSig(ModuleDefMD module, byte[] signature, GenericParamContext gpContext) { return ReadSig(module, module.CorLibTypes, MemoryImageStream.Create(signature), gpContext); } /// /// Reads a signature /// /// The module where the signature is located in /// The signature reader which will be owned by us /// A new instance or null if /// is invalid. public static CallingConventionSig ReadSig(ModuleDefMD module, IBinaryReader signature) { return ReadSig(module, module.CorLibTypes, signature, new GenericParamContext()); } /// /// Reads a signature /// /// The module where the signature is located in /// The signature reader which will be owned by us /// Generic parameter context /// A new instance or null if /// is invalid. public static CallingConventionSig ReadSig(ModuleDefMD module, IBinaryReader signature, GenericParamContext gpContext) { return ReadSig(module, module.CorLibTypes, signature, gpContext); } /// /// Reads a signature /// /// Token resolver /// A instance /// The signature data /// A new instance or null if /// is invalid. public static CallingConventionSig ReadSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, byte[] signature) { return ReadSig(helper, corLibTypes, MemoryImageStream.Create(signature), new GenericParamContext()); } /// /// Reads a signature /// /// Token resolver /// A instance /// The signature data /// Generic parameter context /// A new instance or null if /// is invalid. public static CallingConventionSig ReadSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, byte[] signature, GenericParamContext gpContext) { return ReadSig(helper, corLibTypes, MemoryImageStream.Create(signature), gpContext); } /// /// Reads a signature /// /// Token resolver /// A instance /// The signature reader which will be owned by us /// A new instance or null if /// is invalid. public static CallingConventionSig ReadSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, IBinaryReader signature) { return ReadSig(helper, corLibTypes, signature, new GenericParamContext()); } /// /// Reads a signature /// /// Token resolver /// A instance /// The signature reader which will be owned by us /// Generic parameter context /// A new instance or null if /// is invalid. public static CallingConventionSig ReadSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, IBinaryReader signature, GenericParamContext gpContext) { try { using (var reader = new SignatureReader(helper, corLibTypes, signature, gpContext)) { if (reader.reader.Length == 0) return null; return reader.ReadSig(); } } catch { return null; } } /// /// Reads a type signature from the #Blob stream /// /// Reader module /// #Blob stream offset of signature /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ModuleDefMD readerModule, uint sig) { return ReadTypeSig(readerModule, sig, new GenericParamContext()); } /// /// Reads a type signature from the #Blob stream /// /// Reader module /// #Blob stream offset of signature /// Generic parameter context /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ModuleDefMD readerModule, uint sig, GenericParamContext gpContext) { try { using (var reader = new SignatureReader(readerModule, sig, gpContext)) return reader.ReadType(); } catch { return null; } } /// /// Reads a type signature from the #Blob stream /// /// Reader module /// #Blob stream offset of signature /// If there's any extra data after the signature, it's saved /// here, else this will be null /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ModuleDefMD readerModule, uint sig, out byte[] extraData) { return ReadTypeSig(readerModule, sig, new GenericParamContext(), out extraData); } /// /// Reads a type signature from the #Blob stream /// /// Reader module /// #Blob stream offset of signature /// Generic parameter context /// If there's any extra data after the signature, it's saved /// here, else this will be null /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ModuleDefMD readerModule, uint sig, GenericParamContext gpContext, out byte[] extraData) { try { using (var reader = new SignatureReader(readerModule, sig, gpContext)) { TypeSig ts; try { ts = reader.ReadType(); } catch (IOException) { reader.reader.Position = 0; ts = null; } extraData = reader.GetExtraData(); return ts; } } catch { extraData = null; return null; } } /// /// Reads a signature /// /// The module where the signature is located in /// The signature data /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ModuleDefMD module, byte[] signature) { return ReadTypeSig(module, module.CorLibTypes, MemoryImageStream.Create(signature), new GenericParamContext()); } /// /// Reads a signature /// /// The module where the signature is located in /// The signature data /// Generic parameter context /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ModuleDefMD module, byte[] signature, GenericParamContext gpContext) { return ReadTypeSig(module, module.CorLibTypes, MemoryImageStream.Create(signature), gpContext); } /// /// Reads a signature /// /// The module where the signature is located in /// The signature reader which will be owned by us /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ModuleDefMD module, IBinaryReader signature) { return ReadTypeSig(module, module.CorLibTypes, signature, new GenericParamContext()); } /// /// Reads a signature /// /// The module where the signature is located in /// The signature reader which will be owned by us /// Generic parameter context /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ModuleDefMD module, IBinaryReader signature, GenericParamContext gpContext) { return ReadTypeSig(module, module.CorLibTypes, signature, gpContext); } /// /// Reads a signature /// /// Token resolver /// A instance /// The signature data /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, byte[] signature) { return ReadTypeSig(helper, corLibTypes, MemoryImageStream.Create(signature), new GenericParamContext()); } /// /// Reads a signature /// /// Token resolver /// A instance /// The signature data /// Generic parameter context /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, byte[] signature, GenericParamContext gpContext) { return ReadTypeSig(helper, corLibTypes, MemoryImageStream.Create(signature), gpContext); } /// /// Reads a signature /// /// Token resolver /// A instance /// The signature reader which will be owned by us /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, IBinaryReader signature) { return ReadTypeSig(helper, corLibTypes, signature, new GenericParamContext()); } /// /// Reads a signature /// /// Token resolver /// A instance /// The signature reader which will be owned by us /// Generic parameter context /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, IBinaryReader signature, GenericParamContext gpContext) { byte[] extraData; return ReadTypeSig(helper, corLibTypes, signature, gpContext, out extraData); } /// /// Reads a signature /// /// Token resolver /// A instance /// The signature data /// Generic parameter context /// If there's any extra data after the signature, it's saved /// here, else this will be null /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, byte[] signature, GenericParamContext gpContext, out byte[] extraData) { return ReadTypeSig(helper, corLibTypes, MemoryImageStream.Create(signature), gpContext, out extraData); } /// /// Reads a signature /// /// Token resolver /// A instance /// The signature reader which will be owned by us /// Generic parameter context /// If there's any extra data after the signature, it's saved /// here, else this will be null /// A new instance or null if /// is invalid. public static TypeSig ReadTypeSig(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, IBinaryReader signature, GenericParamContext gpContext, out byte[] extraData) { try { using (var reader = new SignatureReader(helper, corLibTypes, signature, gpContext)) { TypeSig ts; try { ts = reader.ReadType(); } catch (IOException) { reader.reader.Position = 0; ts = null; } extraData = reader.GetExtraData(); return ts; } } catch { extraData = null; return null; } } /// /// Constructor /// /// Reader module /// #Blob stream offset of signature /// Generic parameter context SignatureReader(ModuleDefMD readerModule, uint sig, GenericParamContext gpContext) : this(readerModule, readerModule.CorLibTypes, readerModule.BlobStream.CreateStream(sig), gpContext) { } /// /// Constructor /// /// Token resolver /// A instance /// The signature data /// Generic parameter context SignatureReader(ISignatureReaderHelper helper, ICorLibTypes corLibTypes, IBinaryReader reader, GenericParamContext gpContext) { this.helper = helper; this.corLibTypes = corLibTypes; this.reader = reader; this.gpContext = gpContext; this.recursionCounter = new RecursionCounter(); } byte[] GetExtraData() { if (reader.Position >= reader.Length) return null; return reader.ReadRemainingBytes(); } /// /// Reads the signature /// /// A new instance or null if invalid signature CallingConventionSig ReadSig() { if (!recursionCounter.Increment()) return null; CallingConventionSig result; var callingConvention = (CallingConvention)reader.ReadByte(); switch (callingConvention & CallingConvention.Mask) { case CallingConvention.Default: case CallingConvention.C: case CallingConvention.StdCall: case CallingConvention.ThisCall: case CallingConvention.FastCall: case CallingConvention.VarArg: case CallingConvention.NativeVarArg: result = ReadMethod(callingConvention); break; case CallingConvention.Field: result = ReadField(callingConvention); break; case CallingConvention.LocalSig: result = ReadLocalSig(callingConvention); break; case CallingConvention.Property: result = ReadProperty(callingConvention); break; case CallingConvention.GenericInst: result = ReadGenericInstMethod(callingConvention); break; case CallingConvention.Unmanaged: default: result = null; break; } recursionCounter.Decrement(); return result; } /// /// Reads a /// /// First byte of signature /// A new instance FieldSig ReadField(CallingConvention callingConvention) { return new FieldSig(callingConvention, ReadType()); } /// /// Reads a /// /// First byte of signature /// A new instance MethodSig ReadMethod(CallingConvention callingConvention) { return ReadSig(new MethodSig(callingConvention)); } /// /// Reads a /// /// First byte of signature /// A new instance PropertySig ReadProperty(CallingConvention callingConvention) { return ReadSig(new PropertySig(callingConvention)); } T ReadSig(T methodSig) where T : MethodBaseSig { if (methodSig.Generic) { uint count; if (!reader.ReadCompressedUInt32(out count)) return null; methodSig.GenParamCount = count; } uint numParams; if (!reader.ReadCompressedUInt32(out numParams)) return null; methodSig.RetType = ReadType(); var parameters = methodSig.Params; for (uint i = 0; i < numParams; i++) { var type = ReadType(); if (type is SentinelSig) { if (methodSig.ParamsAfterSentinel == null) methodSig.ParamsAfterSentinel = parameters = ThreadSafeListCreator.Create((int)(numParams - i)); i--; } else parameters.Add(type); } return methodSig; } /// /// Reads a /// /// First byte of signature /// A new instance LocalSig ReadLocalSig(CallingConvention callingConvention) { uint count; if (!reader.ReadCompressedUInt32(out count)) return null; var sig = new LocalSig(callingConvention, count); var locals = sig.Locals; for (uint i = 0; i < count; i++) locals.Add(ReadType()); return sig; } /// /// Reads a /// /// First byte of signature /// A new instance GenericInstMethodSig ReadGenericInstMethod(CallingConvention callingConvention) { uint count; if (!reader.ReadCompressedUInt32(out count)) return null; var sig = new GenericInstMethodSig(callingConvention, count); var args = sig.GenericArguments; for (uint i = 0; i < count; i++) args.Add(ReadType()); return sig; } /// /// Reads the next type /// /// A new instance or null if invalid element type TypeSig ReadType() { if (!recursionCounter.Increment()) return null; uint num; TypeSig nextType, result = null; switch ((ElementType)reader.ReadByte()) { case ElementType.Void: result = corLibTypes.Void; break; case ElementType.Boolean: result = corLibTypes.Boolean; break; case ElementType.Char: result = corLibTypes.Char; break; case ElementType.I1: result = corLibTypes.SByte; break; case ElementType.U1: result = corLibTypes.Byte; break; case ElementType.I2: result = corLibTypes.Int16; break; case ElementType.U2: result = corLibTypes.UInt16; break; case ElementType.I4: result = corLibTypes.Int32; break; case ElementType.U4: result = corLibTypes.UInt32; break; case ElementType.I8: result = corLibTypes.Int64; break; case ElementType.U8: result = corLibTypes.UInt64; break; case ElementType.R4: result = corLibTypes.Single; break; case ElementType.R8: result = corLibTypes.Double; break; case ElementType.String: result = corLibTypes.String; break; case ElementType.TypedByRef:result = corLibTypes.TypedReference; break; case ElementType.I: result = corLibTypes.IntPtr; break; case ElementType.U: result = corLibTypes.UIntPtr; break; case ElementType.Object: result = corLibTypes.Object; break; case ElementType.Ptr: result = new PtrSig(ReadType()); break; case ElementType.ByRef: result = new ByRefSig(ReadType()); break; case ElementType.ValueType: result = new ValueTypeSig(ReadTypeDefOrRef()); break; case ElementType.Class: result = new ClassSig(ReadTypeDefOrRef()); break; case ElementType.FnPtr: result = new FnPtrSig(ReadSig()); break; case ElementType.SZArray: result = new SZArraySig(ReadType()); break; case ElementType.CModReqd: result = new CModReqdSig(ReadTypeDefOrRef(), ReadType()); break; case ElementType.CModOpt: result = new CModOptSig(ReadTypeDefOrRef(), ReadType()); break; case ElementType.Sentinel: result = new SentinelSig(); break; case ElementType.Pinned: result = new PinnedSig(ReadType()); break; case ElementType.Var: if (!reader.ReadCompressedUInt32(out num)) break; result = new GenericVar(num, gpContext.Type); break; case ElementType.MVar: if (!reader.ReadCompressedUInt32(out num)) break; result = new GenericMVar(num, gpContext.Method); break; case ElementType.ValueArray: nextType = ReadType(); if (!reader.ReadCompressedUInt32(out num)) break; result = new ValueArraySig(nextType, num); break; case ElementType.Module: if (!reader.ReadCompressedUInt32(out num)) break; result = new ModuleSig(num, ReadType()); break; case ElementType.GenericInst: nextType = ReadType(); if (!reader.ReadCompressedUInt32(out num)) break; var genericInstSig = new GenericInstSig(nextType as ClassOrValueTypeSig, num); var args = genericInstSig.GenericArguments; for (uint i = 0; i < num; i++) args.Add(ReadType()); result = genericInstSig; break; case ElementType.Array: nextType = ReadType(); uint rank; if (!reader.ReadCompressedUInt32(out rank)) break; if (rank == 0) { result = new ArraySig(nextType, rank); break; } if (!reader.ReadCompressedUInt32(out num)) break; var sizes = new List((int)num); for (uint i = 0; i < num; i++) { uint size; if (!reader.ReadCompressedUInt32(out size)) goto exit; sizes.Add(size); } if (!reader.ReadCompressedUInt32(out num)) break; var lowerBounds = new List((int)num); for (uint i = 0; i < num; i++) { int size; if (!reader.ReadCompressedInt32(out size)) goto exit; lowerBounds.Add(size); } result = new ArraySig(nextType, rank, sizes, lowerBounds); break; case ElementType.Internal: IntPtr address; if (IntPtr.Size == 4) address = new IntPtr(reader.ReadInt32()); else address = new IntPtr(reader.ReadInt64()); result = helper.ConvertRTInternalAddress(address); break; case ElementType.End: case ElementType.R: default: result = null; break; } exit: recursionCounter.Decrement(); return result; } /// /// Reads a TypeDefOrRef /// /// A instance ITypeDefOrRef ReadTypeDefOrRef() { uint codedToken; if (!reader.ReadCompressedUInt32(out codedToken)) return null; return helper.ResolveTypeDefOrRef(codedToken, gpContext); } /// public void Dispose() { if (reader != null) reader.Dispose(); } } } dnlib-2.1_VS2010/src/DotNet/StandAloneSig.cs000066400000000000000000000132771325033663500204050ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the StandAloneSig table /// public abstract class StandAloneSig : IHasCustomAttribute, IHasCustomDebugInformation, IContainsGenericParameter { /// /// The row id in its table /// protected uint rid; /// public MDToken MDToken { get { return new MDToken(Table.StandAloneSig, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int HasCustomAttributeTag { get { return 11; } } /// /// From column StandAloneSig.Signature /// public CallingConventionSig Signature { get { return signature; } set { signature = value; } } /// protected CallingConventionSig signature; /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 11; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// /// Gets/sets the method sig /// public MethodSig MethodSig { get { return signature as MethodSig; } set { signature = value; } } /// /// Gets/sets the locals sig /// public LocalSig LocalSig { get { return signature as LocalSig; } set { signature = value; } } /// public bool ContainsGenericParameter { get { return TypeHelper.ContainsGenericParameter(this); } } } /// /// A StandAloneSig row created by the user and not present in the original .NET file /// public class StandAloneSigUser : StandAloneSig { /// /// Default constructor /// public StandAloneSigUser() { } /// /// Constructor /// /// A locals sig public StandAloneSigUser(LocalSig localSig) { this.signature = localSig; } /// /// Constructor /// /// A method sig public StandAloneSigUser(MethodSig methodSig) { this.signature = methodSig; } } /// /// Created from a row in the StandAloneSig table /// sealed class StandAloneSigMD : StandAloneSig, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; readonly GenericParamContext gpContext; /// public uint OrigRid { get { return origRid; } } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.StandAloneSig, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), gpContext, list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this StandAloneSig row /// Row ID /// Generic parameter context /// If is null /// If is invalid public StandAloneSigMD(ModuleDefMD readerModule, uint rid, GenericParamContext gpContext) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.StandAloneSigTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("StandAloneSig rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; this.gpContext = gpContext; uint signature = readerModule.TablesStream.ReadStandAloneSigRow2(origRid); this.signature = readerModule.ReadSignature(signature, gpContext); } } } dnlib-2.1_VS2010/src/DotNet/StrongNameKey.cs000066400000000000000000000513751325033663500204410ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using System.Runtime.Serialization; using System.Security.Cryptography; using dnlib.Threading; namespace dnlib.DotNet { /// /// Thrown if the strong name key or public key is invalid /// [Serializable] public class InvalidKeyException : Exception { /// /// Default constructor /// public InvalidKeyException() { } /// /// Constructor /// /// Error message public InvalidKeyException(string message) : base(message) { } /// /// Constructor /// /// Error message /// Other exception public InvalidKeyException(string message, Exception innerException) : base(message, innerException) { } /// /// Constructor /// /// /// protected InvalidKeyException(SerializationInfo info, StreamingContext context) : base(info, context) { } } /// /// Type of signature algorithm. See WinCrypt.h in the Windows SDK /// public enum SignatureAlgorithm : uint { /// /// RSA signature algorithm /// CALG_RSA_SIGN = 0x00002400, } static class StrongNameUtils { public static byte[] ReadBytesReverse(this BinaryReader reader, int len) { var data = reader.ReadBytes(len); if (data.Length != len) throw new InvalidKeyException("Can't read more bytes"); Array.Reverse(data); return data; } public static void WriteReverse(this BinaryWriter writer, byte[] data) { var d = (byte[])data.Clone(); Array.Reverse(d); writer.Write(d); } } /// /// A public key /// public sealed class StrongNamePublicKey { const uint RSA1_SIG = 0x31415352; SignatureAlgorithm signatureAlgorithm; AssemblyHashAlgorithm hashAlgorithm; byte[] modulus; byte[] publicExponent; /// /// Gets/sets the signature algorithm /// public SignatureAlgorithm SignatureAlgorithm { get { return signatureAlgorithm; } set { signatureAlgorithm = value; } } /// /// Gets/sets the hash algorithm /// public AssemblyHashAlgorithm HashAlgorithm { get { return hashAlgorithm; } set { hashAlgorithm = value; } } /// /// Gets/sets the modulus /// public byte[] Modulus { get { return modulus; } set { modulus = value; } } /// /// Gets/sets the public exponent /// public byte[] PublicExponent { get { return publicExponent; } set { if (value == null || value.Length != 4) throw new ArgumentException("PublicExponent must be exactly 4 bytes"); publicExponent = value; } } /// /// Default constructor /// public StrongNamePublicKey() { } /// /// Constructor /// /// Modulus /// Public exponent public StrongNamePublicKey(byte[] modulus, byte[] publicExponent) : this(modulus, publicExponent, AssemblyHashAlgorithm.SHA1, SignatureAlgorithm.CALG_RSA_SIGN) { } /// /// Constructor /// /// Modulus /// Public exponent /// Hash algorithm public StrongNamePublicKey(byte[] modulus, byte[] publicExponent, AssemblyHashAlgorithm hashAlgorithm) : this(modulus, publicExponent, hashAlgorithm, SignatureAlgorithm.CALG_RSA_SIGN) { } /// /// Constructor /// /// Modulus /// Public exponent /// Hash algorithm /// Signature algorithm public StrongNamePublicKey(byte[] modulus, byte[] publicExponent, AssemblyHashAlgorithm hashAlgorithm, SignatureAlgorithm signatureAlgorithm) { this.signatureAlgorithm = signatureAlgorithm; this.hashAlgorithm = hashAlgorithm; this.modulus = modulus; this.publicExponent = publicExponent; } /// /// Constructor /// /// Public key public StrongNamePublicKey(PublicKey pk) : this(pk.Data) { } /// /// Constructor /// /// Public key data /// Strong name key is invalid public StrongNamePublicKey(byte[] pk) { Initialize(new BinaryReader(new MemoryStream(pk))); } /// /// Constructor /// /// Public key file /// Strong name key is invalid public StrongNamePublicKey(string filename) { using (var fileStream = File.OpenRead(filename)) Initialize(new BinaryReader(fileStream)); } /// /// Constructor /// /// Public key stream /// Strong name key is invalid public StrongNamePublicKey(Stream stream) { Initialize(new BinaryReader(stream)); } /// /// Constructor /// /// Public key reader /// Strong name key is invalid public StrongNamePublicKey(BinaryReader reader) { Initialize(reader); } void Initialize(BinaryReader reader) { try { // Read PublicKeyBlob signatureAlgorithm = (SignatureAlgorithm)reader.ReadUInt32(); hashAlgorithm = (AssemblyHashAlgorithm)reader.ReadUInt32(); /*int pkLen = */reader.ReadInt32(); // Read PUBLICKEYSTRUC if (reader.ReadByte() != 6) throw new InvalidKeyException("Not a public key"); if (reader.ReadByte() != 2) throw new InvalidKeyException("Invalid version"); reader.ReadUInt16(); // reserved if ((SignatureAlgorithm)reader.ReadUInt32() != SignatureAlgorithm.CALG_RSA_SIGN) throw new InvalidKeyException("Not RSA sign"); // Read RSAPUBKEY if (reader.ReadUInt32() != RSA1_SIG) // magic = RSA1 throw new InvalidKeyException("Invalid RSA1 magic"); uint bitLength = reader.ReadUInt32(); publicExponent = reader.ReadBytesReverse(4); modulus = reader.ReadBytesReverse((int)(bitLength / 8)); } catch (IOException ex) { throw new InvalidKeyException("Invalid public key", ex); } } /// /// Creates a public key blob /// public byte[] CreatePublicKey() { return CreatePublicKey(signatureAlgorithm, hashAlgorithm, modulus, publicExponent); } internal static byte[] CreatePublicKey(SignatureAlgorithm sigAlg, AssemblyHashAlgorithm hashAlg, byte[] modulus, byte[] publicExponent) { if (sigAlg != SignatureAlgorithm.CALG_RSA_SIGN) throw new ArgumentException("Signature algorithm must be RSA"); var outStream = new MemoryStream(); var writer = new BinaryWriter(outStream); writer.Write((uint)sigAlg); // SigAlgID writer.Write((uint)hashAlg); // HashAlgID writer.Write(0x14 + modulus.Length);// cbPublicKey writer.Write((byte)6); // bType (public key) writer.Write((byte)2); // bVersion writer.Write((ushort)0); // reserved writer.Write((uint)sigAlg); // aiKeyAlg writer.Write(RSA1_SIG); // magic (RSA1) writer.Write(modulus.Length * 8); // bitlen writer.WriteReverse(publicExponent);// pubexp writer.WriteReverse(modulus); // modulus return outStream.ToArray(); } /// public override string ToString() { return Utils.ToHex(CreatePublicKey(), false); } } /// /// Stores a strong name key pair /// public sealed class StrongNameKey { const uint RSA2_SIG = 0x32415352; byte[] publicKey; AssemblyHashAlgorithm hashAlg; byte[] publicExponent; byte[] modulus; byte[] prime1; byte[] prime2; byte[] exponent1; byte[] exponent2; byte[] coefficient; byte[] privateExponent; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// /// Gets the public key /// public byte[] PublicKey { get { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (publicKey == null) publicKey = CreatePublicKey_NoLock(); return publicKey; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Gets the strong name signature size in bytes /// public int SignatureSize { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return modulus.Length; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } } /// /// Gets/sets the public key hash algorithm. It's usually /// public AssemblyHashAlgorithm HashAlgorithm { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return hashAlg; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (hashAlg == value) return; publicKey = null; hashAlg = value; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Gets/sets the public exponent /// public byte[] PublicExponent { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return publicExponent; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } set { if (value == null || value.Length != 4) throw new ArgumentException("PublicExponent must be exactly 4 bytes"); #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif publicExponent = value; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Gets/sets the modulus /// public byte[] Modulus { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return modulus; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } set { if (value == null) throw new ArgumentNullException("value"); #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif modulus = value; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Gets/sets prime1 /// public byte[] Prime1 { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return prime1; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } set { if (value == null) throw new ArgumentNullException("value"); #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif prime1 = value; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Gets/sets prime2 /// public byte[] Prime2 { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return prime2; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } set { if (value == null) throw new ArgumentNullException("value"); #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif prime2 = value; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Gets/sets exponent1 /// public byte[] Exponent1 { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return exponent1; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } set { if (value == null) throw new ArgumentNullException("value"); #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif exponent1 = value; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Gets/sets exponent2 /// public byte[] Exponent2 { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return exponent2; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } set { if (value == null) throw new ArgumentNullException("value"); #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif exponent2 = value; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Gets/sets the coefficient /// public byte[] Coefficient { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return coefficient; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } set { if (value == null) throw new ArgumentNullException("value"); #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif coefficient = value; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Gets/sets the private exponent /// public byte[] PrivateExponent { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return privateExponent; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } set { if (value == null) throw new ArgumentNullException("value"); #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif privateExponent = value; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Default constructor /// public StrongNameKey() { } /// /// Constructor /// /// Strong name key data /// Strong name key is invalid public StrongNameKey(byte[] keyData) { Initialize(new BinaryReader(new MemoryStream(keyData))); } /// /// Constructor /// /// Strong name key file /// Strong name key is invalid public StrongNameKey(string filename) { using (var fileStream = File.OpenRead(filename)) Initialize(new BinaryReader(fileStream)); } /// /// Constructor /// /// Strong name key stream /// Strong name key is invalid public StrongNameKey(Stream stream) { Initialize(new BinaryReader(stream)); } /// /// Constructor /// /// Strong name key reader /// Strong name key is invalid public StrongNameKey(BinaryReader reader) { Initialize(reader); } /// /// Initializes the public/private key pair data /// /// Public/private key pair reader /// Strong name key is invalid public void Initialize(BinaryReader reader) { /* * Links: * http://msdn.microsoft.com/en-us/library/cc250013%28v=prot.20%29.aspx * http://msdn.microsoft.com/en-us/library/windows/desktop/aa387689%28v=vs.85%29.aspx * * struct PublicKeyBlob { * unsigned int SigAlgID; // sig algorithm used to create the sig (00002400 = CALG_RSA_SIGN) * unsigned int HashAlgID; // hash alg used to create the sig (usually 00008004 = CALG_SHA1) * ULONG cbPublicKey; // Size of the data that follows * // the rest is here * } * * typedef struct _PUBLICKEYSTRUC { * BYTE bType; * BYTE bVersion; * WORD reserved; * ALG_ID aiKeyAlg; * } BLOBHEADER, PUBLICKEYSTRUC; * * typedef struct _RSAPUBKEY { * DWORD magic; * DWORD bitlen; * DWORD pubexp; * } RSAPUBKEY; * * Format of public key * PublicKeyBlob * PUBLICKEYSTRUC publickeystruc; * RSAPUBKEY rsapubkey; * BYTE modulus[rsapubkey.bitlen/8] * * Format of public/private key pair * PUBLICKEYSTRUC publickeystruc; * RSAPUBKEY rsapubkey; * BYTE modulus[rsapubkey.bitlen/8]; * BYTE prime1[rsapubkey.bitlen/16]; // aka P * BYTE prime2[rsapubkey.bitlen/16]; // aka Q * BYTE exponent1[rsapubkey.bitlen/16]; // aka DP * BYTE exponent2[rsapubkey.bitlen/16]; // aka DQ * BYTE coefficient[rsapubkey.bitlen/16]; // aka IQ * BYTE privateExponent[rsapubkey.bitlen/8];// aka D */ try { publicKey = null; // Read PUBLICKEYSTRUC if (reader.ReadByte() != 7) throw new InvalidKeyException("Not a public/private key pair"); if (reader.ReadByte() != 2) throw new InvalidKeyException("Invalid version"); reader.ReadUInt16(); // reserved if ((SignatureAlgorithm)reader.ReadUInt32() != SignatureAlgorithm.CALG_RSA_SIGN) throw new InvalidKeyException("Not RSA sign"); // Read RSAPUBKEY if (reader.ReadUInt32() != RSA2_SIG) // magic = RSA2 throw new InvalidKeyException("Invalid RSA2 magic"); uint bitLength = reader.ReadUInt32(); publicExponent = reader.ReadBytesReverse(4); int len8 = (int)(bitLength / 8); int len16 = (int)(bitLength / 16); // Read the rest modulus = reader.ReadBytesReverse(len8); prime1 = reader.ReadBytesReverse(len16); prime2 = reader.ReadBytesReverse(len16); exponent1 = reader.ReadBytesReverse(len16); exponent2 = reader.ReadBytesReverse(len16); coefficient = reader.ReadBytesReverse(len16); privateExponent = reader.ReadBytesReverse(len8); } catch (IOException ex) { throw new InvalidKeyException("Couldn't read strong name key", ex); } } byte[] CreatePublicKey_NoLock() { var halg = hashAlg == 0 ? AssemblyHashAlgorithm.SHA1 : hashAlg; return StrongNamePublicKey.CreatePublicKey(SignatureAlgorithm.CALG_RSA_SIGN, halg, modulus, publicExponent); } /// /// Creates an instance /// public RSA CreateRSA() { RSAParameters rsaParams; #if THREAD_SAFE theLock.EnterReadLock(); try { #endif rsaParams = new RSAParameters { Exponent = publicExponent, Modulus = modulus, P = prime1, Q = prime2, DP = exponent1, DQ = exponent2, InverseQ = coefficient, D = privateExponent, }; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif var rsa = RSA.Create(); try { rsa.ImportParameters(rsaParams); return rsa; } catch { ((IDisposable)rsa).Dispose(); throw; } } /// /// Creates a strong name blob /// public byte[] CreateStrongName() { var outStream = new MemoryStream(); var writer = new BinaryWriter(outStream); writer.Write((byte)7); // bType (public/private key) writer.Write((byte)2); // bVersion writer.Write((ushort)0); // reserved writer.Write((uint)SignatureAlgorithm.CALG_RSA_SIGN); // aiKeyAlg writer.Write(RSA2_SIG); // magic (RSA2) #if THREAD_SAFE theLock.EnterReadLock(); try { #endif writer.Write(modulus.Length * 8); // bitlen writer.WriteReverse(publicExponent); writer.WriteReverse(modulus); writer.WriteReverse(prime1); writer.WriteReverse(prime2); writer.WriteReverse(exponent1); writer.WriteReverse(exponent2); writer.WriteReverse(coefficient); writer.WriteReverse(privateExponent); #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif return outStream.ToArray(); } /// /// Creates a counter signature, just like /// sn -a IdentityPubKey.snk IdentityKey.snk SignaturePubKey.snk can do. /// The public key sn prints is 's value. /// /// Identity public key /// Identity strong name key pair /// Signature public key /// The counter signature as a hex string public static string CreateCounterSignatureAsString(StrongNamePublicKey identityPubKey, StrongNameKey identityKey, StrongNamePublicKey signaturePubKey) { var counterSignature = CreateCounterSignature(identityPubKey, identityKey, signaturePubKey); return Utils.ToHex(counterSignature, false); } /// /// Creates a counter signature, just like /// sn -a IdentityPubKey.snk IdentityKey.snk SignaturePubKey.snk can do. /// The public key sn prints is 's value. /// /// Identity public key /// Identity strong name key pair /// Signature public key /// The counter signature public static byte[] CreateCounterSignature(StrongNamePublicKey identityPubKey, StrongNameKey identityKey, StrongNamePublicKey signaturePubKey) { var hash = AssemblyHash.Hash(signaturePubKey.CreatePublicKey(), identityPubKey.HashAlgorithm); using (var rsa = identityKey.CreateRSA()) { var rsaFmt = new RSAPKCS1SignatureFormatter(rsa); string hashName = identityPubKey.HashAlgorithm.GetName(); rsaFmt.SetHashAlgorithm(hashName); var snSig = rsaFmt.CreateSignature(hash); Array.Reverse(snSig); return snSig; } } } } dnlib-2.1_VS2010/src/DotNet/StrongNameSigner.cs000066400000000000000000000135341325033663500211330ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using System.Security.Cryptography; namespace dnlib.DotNet { /// /// Strong name signs an assembly. It supports normal strong name signing and the new /// (.NET 4.5) enhanced strong name signing. /// public struct StrongNameSigner { readonly Stream stream; readonly long baseOffset; /// /// Constructor /// /// .NET PE file stream public StrongNameSigner(Stream stream) : this(stream, 0) { } /// /// Constructor /// /// .NET PE file stream /// Offset in of the first byte of /// the PE file. public StrongNameSigner(Stream stream, long baseOffset) { this.stream = stream; this.baseOffset = baseOffset; } /// /// Calculates the strong name signature and writes it to the stream. The signature /// is also returned. /// /// Strong name key used for signing /// Offset (relative to the start of the PE file) of the strong /// name signature. /// The strong name signature public byte[] WriteSignature(StrongNameKey snk, long snSigOffset) { var sign = CalculateSignature(snk, snSigOffset); stream.Position = baseOffset + snSigOffset; stream.Write(sign, 0, sign.Length); return sign; } /// /// Calculates and returns the strong name signature /// /// Strong name key used for signing /// Offset (relative to start of PE file) of the strong /// name signature. /// The strong name signature public byte[] CalculateSignature(StrongNameKey snk, long snSigOffset) { uint snSigSize = (uint)snk.SignatureSize; var hashAlg = snk.HashAlgorithm == 0 ? AssemblyHashAlgorithm.SHA1 : snk.HashAlgorithm; var hash = StrongNameHashData(hashAlg, snSigOffset, snSigSize); var snSig = GetStrongNameSignature(snk, hashAlg, hash); if (snSig.Length != snSigSize) throw new InvalidOperationException("Invalid strong name signature size"); return snSig; } /// /// Strong name hashes the .NET file /// /// Hash algorithm /// Strong name sig offset (relative to start of .NET PE file) /// Size of strong name signature /// The strong name hash of the .NET file byte[] StrongNameHashData(AssemblyHashAlgorithm hashAlg, long snSigOffset, uint snSigSize) { var reader = new BinaryReader(stream); snSigOffset += baseOffset; long snSigOffsetEnd = snSigOffset + snSigSize; using (var hasher = new AssemblyHash(hashAlg)) { byte[] buffer = new byte[0x8000]; // Hash the DOS header. It's defined to be all data from the start of // the file up to the NT headers. stream.Position = baseOffset + 0x3C; uint ntHeadersOffs = reader.ReadUInt32(); stream.Position = baseOffset; hasher.Hash(stream, ntHeadersOffs, buffer); // Hash NT headers, but hash authenticode + checksum as 0s stream.Position += 6; int numSections = reader.ReadUInt16(); stream.Position -= 8; hasher.Hash(stream, 0x18, buffer); // magic + FileHeader bool is32bit = reader.ReadUInt16() == 0x010B; stream.Position -= 2; int optHeaderSize = is32bit ? 0x60 : 0x70; if (stream.Read(buffer, 0, optHeaderSize) != optHeaderSize) throw new IOException("Could not read data"); // Clear checksum for (int i = 0; i < 4; i++) buffer[0x40 + i] = 0; hasher.Hash(buffer, 0, optHeaderSize); const int imageDirsSize = 16 * 8; if (stream.Read(buffer, 0, imageDirsSize) != imageDirsSize) throw new IOException("Could not read data"); // Clear authenticode data dir for (int i = 0; i < 8; i++) buffer[4 * 8 + i] = 0; hasher.Hash(buffer, 0, imageDirsSize); // Hash section headers long sectHeadersOffs = stream.Position; hasher.Hash(stream, (uint)numSections * 0x28, buffer); // Hash all raw section data but make sure we don't hash the location // where the strong name signature will be stored. for (int i = 0; i < numSections; i++) { stream.Position = sectHeadersOffs + i * 0x28 + 0x10; uint sizeOfRawData = reader.ReadUInt32(); uint pointerToRawData = reader.ReadUInt32(); stream.Position = baseOffset + pointerToRawData; while (sizeOfRawData > 0) { var pos = stream.Position; if (snSigOffset <= pos && pos < snSigOffsetEnd) { uint skipSize = (uint)(snSigOffsetEnd - pos); if (skipSize >= sizeOfRawData) break; sizeOfRawData -= skipSize; stream.Position += skipSize; continue; } if (pos >= snSigOffsetEnd) { hasher.Hash(stream, sizeOfRawData, buffer); break; } uint maxLen = (uint)Math.Min(snSigOffset - pos, sizeOfRawData); hasher.Hash(stream, maxLen, buffer); sizeOfRawData -= maxLen; } } return hasher.ComputeHash(); } } /// /// Returns the strong name signature /// /// Strong name key /// Hash algorithm /// Strong name hash of the .NET PE file /// Strong name signature byte[] GetStrongNameSignature(StrongNameKey snk, AssemblyHashAlgorithm hashAlg, byte[] hash) { using (var rsa = snk.CreateRSA()) { var rsaFmt = new RSAPKCS1SignatureFormatter(rsa); string hashName = hashAlg.GetName() ?? AssemblyHashAlgorithm.SHA1.GetName(); rsaFmt.SetHashAlgorithm(hashName); var snSig = rsaFmt.CreateSignature(hash); Array.Reverse(snSig); return snSig; } } } } dnlib-2.1_VS2010/src/DotNet/TIAHelper.cs000066400000000000000000000143661325033663500174670ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info // See coreclr/src/vm/siginfo.cpp using System; using System.Diagnostics; namespace dnlib.DotNet { /// /// System.Runtime.InteropServices.TypeIdentifierAttribute helper code used by /// static class TIAHelper { struct Info : IEquatable { public readonly UTF8String Scope; public readonly UTF8String Identifier; public Info(UTF8String scope, UTF8String identifier) { this.Scope = scope; this.Identifier = identifier; } public bool Equals(Info other) { return stricmp(Scope, other.Scope) && UTF8String.Equals(Identifier, other.Identifier); } static bool stricmp(UTF8String a, UTF8String b) { var da = (object)a == null ? null : a.Data; var db = (object)b == null ? null : b.Data; if (da == db) return true; if (da == null || db == null) return false; if (da.Length != db.Length) return false; for (int i = 0; i < da.Length; i++) { byte ba = da[i], bb = db[i]; if ((byte)'A' <= ba && ba <= (byte)'Z') ba = (byte)(ba - 'A' + 'a'); if ((byte)'A' <= bb && bb <= (byte)'Z') bb = (byte)(bb - 'A' + 'a'); if (ba != bb) return false; } return true; } } static Info? GetInfo(TypeDef td) { if (td == null) return null; if (td.IsWindowsRuntime) return null; UTF8String scope = null, identifier = null; var tia = td.CustomAttributes.Find("System.Runtime.InteropServices.TypeIdentifierAttribute"); if (tia != null) { if (tia.ConstructorArguments.Count >= 2) { if (tia.ConstructorArguments[0].Type.GetElementType() != ElementType.String) return null; if (tia.ConstructorArguments[1].Type.GetElementType() != ElementType.String) return null; scope = tia.ConstructorArguments[0].Value as UTF8String ?? tia.ConstructorArguments[0].Value as string; identifier = tia.ConstructorArguments[1].Value as UTF8String ?? tia.ConstructorArguments[1].Value as string; } } else { var mod = td.Module; var asm = mod == null ? null : mod.Assembly; if (asm == null) return null; bool isTypeLib = asm.CustomAttributes.IsDefined("System.Runtime.InteropServices.ImportedFromTypeLibAttribute") || asm.CustomAttributes.IsDefined("System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute"); if (!isTypeLib) return null; } if (UTF8String.IsNull(identifier)) { CustomAttribute gca; if (td.IsInterface && td.IsImport) gca = td.CustomAttributes.Find("System.Runtime.InteropServices.GuidAttribute"); else { var mod = td.Module; var asm = mod == null ? null : mod.Assembly; if (asm == null) return null; gca = asm.CustomAttributes.Find("System.Runtime.InteropServices.GuidAttribute"); } if (gca == null) return null; if (gca.ConstructorArguments.Count < 1) return null; if (gca.ConstructorArguments[0].Type.GetElementType() != ElementType.String) return null; scope = gca.ConstructorArguments[0].Value as UTF8String ?? gca.ConstructorArguments[0].Value as string; var ns = td.Namespace; var name = td.Name; if (UTF8String.IsNullOrEmpty(ns)) identifier = name; else if (UTF8String.IsNullOrEmpty(name)) identifier = new UTF8String(Concat(ns.Data, (byte)'.', empty)); else identifier = new UTF8String(Concat(ns.Data, (byte)'.', name.Data)); } return new Info(scope, identifier); } static readonly byte[] empty = new byte[0]; static byte[] Concat(byte[] a, byte b, byte[] c) { var data = new byte[a.Length + 1 + c.Length]; for (int i = 0; i < a.Length; i++) data[i] = a[i]; data[a.Length] = b; for (int i = 0, j = a.Length + 1; i < c.Length; i++, j++) data[j] = c[i]; return data; } static bool CheckEquivalent(TypeDef td) { Debug.Assert(td != null); for (int i = 0; td != null && i < 1000; i++) { if (i != 0) { var info = GetInfo(td); if (info == null) return false; } bool f; if (td.IsInterface) f = td.IsImport || td.CustomAttributes.IsDefined("System.Runtime.InteropServices.ComEventInterfaceAttribute"); else f = td.IsValueType || td.IsDelegate; if (!f) return false; if (td.GenericParameters.Count > 0) return false; var declType = td.DeclaringType; if (declType == null) return td.IsPublic; if (!td.IsNestedPublic) return false; td = declType; } return false; } public static bool Equivalent(TypeDef td1, TypeDef td2) { var info1 = GetInfo(td1); if (info1 == null) return false; var info2 = GetInfo(td2); if (info2 == null) return false; if (!CheckEquivalent(td1) || !CheckEquivalent(td2)) return false; if (!info1.Value.Equals(info2.Value)) return false; // Caller has already compared names of the types and any declaring types for (int i = 0; i < 1000; i++) { if (td1.IsInterface) { if (!td2.IsInterface) return false; } else { var bt1 = td1.BaseType; var bt2 = td2.BaseType; if (bt1 == null || bt2 == null) return false; if (td1.IsDelegate) { if (!td2.IsDelegate) return false; if (!DelegateEquals(td1, td2)) return false; } else if (td1.IsValueType) { if (td1.IsEnum != td2.IsEnum) return false; if (!td2.IsValueType) return false; if (!ValueTypeEquals(td1, td2, td1.IsEnum)) return false; } else return false; } td1 = td1.DeclaringType; td2 = td2.DeclaringType; if (td1 == null && td2 == null) break; if (td1 == null || td2 == null) return false; } return true; } static bool DelegateEquals(TypeDef td1, TypeDef td2) { var invoke1 = td1.FindMethod(InvokeString); var invoke2 = td2.FindMethod(InvokeString); if (invoke1 == null || invoke2 == null) return false; //TODO: Compare method signatures. Prevent infinite recursion... return true; } static readonly UTF8String InvokeString = new UTF8String("Invoke"); static bool ValueTypeEquals(TypeDef td1, TypeDef td2, bool isEnum) { if (td1.Methods.Count != 0 || td2.Methods.Count != 0) return false; //TODO: Compare the fields. Prevent infinite recursion... return true; } } } dnlib-2.1_VS2010/src/DotNet/TypeAttributes.cs000066400000000000000000000070341325033663500206740ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.DotNet { /// /// TypeDef and ExportedType flags. See CorHdr.h/CorTypeAttr /// [Flags] public enum TypeAttributes : uint { /// Use this mask to retrieve the type visibility information. VisibilityMask = 0x00000007, /// Class is not public scope. NotPublic = 0x00000000, /// Class is public scope. Public = 0x00000001, /// Class is nested with public visibility. NestedPublic = 0x00000002, /// Class is nested with private visibility. NestedPrivate = 0x00000003, /// Class is nested with family visibility. NestedFamily = 0x00000004, /// Class is nested with assembly visibility. NestedAssembly = 0x00000005, /// Class is nested with family and assembly visibility. NestedFamANDAssem = 0x00000006, /// Class is nested with family or assembly visibility. NestedFamORAssem = 0x00000007, /// Use this mask to retrieve class layout information LayoutMask = 0x00000018, /// Class fields are auto-laid out AutoLayout = 0x00000000, /// Class fields are laid out sequentially SequentialLayout = 0x00000008, /// Layout is supplied explicitly ExplicitLayout = 0x00000010, /// Use this mask to retrieve class semantics information. ClassSemanticsMask = 0x00000020, /// Use this mask to retrieve class semantics information. ClassSemanticMask = ClassSemanticsMask, /// Type is a class. Class = 0x00000000, /// Type is an interface. Interface = 0x00000020, /// Class is abstract Abstract = 0x00000080, /// Class is concrete and may not be extended Sealed = 0x00000100, /// Class name is special. Name describes how. SpecialName = 0x00000400, /// Class / interface is imported Import = 0x00001000, /// The class is Serializable. Serializable = 0x00002000, /// The type is a Windows Runtime type WindowsRuntime = 0x00004000, /// Use StringFormatMask to retrieve string information for native interop StringFormatMask = 0x00030000, /// LPTSTR is interpreted as ANSI in this class AnsiClass = 0x00000000, /// LPTSTR is interpreted as UNICODE UnicodeClass = 0x00010000, /// LPTSTR is interpreted automatically AutoClass = 0x00020000, /// A non-standard encoding specified by CustomFormatMask CustomFormatClass = 0x00030000, /// Use this mask to retrieve non-standard encoding information for native interop. The meaning of the values of these 2 bits is unspecified. CustomFormatMask = 0x00C00000, /// Initialize the class any time before first static field access. BeforeFieldInit = 0x00100000, /// This ExportedType is a type forwarder. Forwarder = 0x00200000, /// Flags reserved for runtime use. ReservedMask = 0x00040800, /// Runtime should check name encoding. RTSpecialName = 0x00000800, /// Class has security associate with it. HasSecurity = 0x00040000, } } dnlib-2.1_VS2010/src/DotNet/TypeDef.cs000066400000000000000000002366451325033663500172600ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Threading; using dnlib.Utils; using dnlib.DotNet.MD; using dnlib.DotNet.Emit; using dnlib.Threading; using dnlib.DotNet.Pdb; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the TypeDef table /// public abstract class TypeDef : ITypeDefOrRef, IHasCustomAttribute, IHasDeclSecurity, IMemberRefParent, ITypeOrMethodDef, IHasCustomDebugInformation, IListListener, IListListener, IListListener, IListListener, IListListener, IListListener, IMemberRefResolver, IMemberDef { /// /// The row id in its table /// protected uint rid; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// public MDToken MDToken { get { return new MDToken(Table.TypeDef, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int TypeDefOrRefTag { get { return 0; } } /// public int HasCustomAttributeTag { get { return 3; } } /// public int HasDeclSecurityTag { get { return 0; } } /// public int MemberRefParentTag { get { return 0; } } /// public int TypeOrMethodDefTag { get { return 0; } } /// int IGenericParameterProvider.NumberOfGenericParameters { get { return GenericParameters.Count; } } /// string IType.TypeName { get { return FullNameCreator.Name(this, false, null); } } /// public string ReflectionName { get { return FullNameCreator.Name(this, true, null); } } /// string IType.Namespace { get { return FullNameCreator.Namespace(this, false, null); } } /// public string ReflectionNamespace { get { return FullNameCreator.Namespace(this, true, null); } } /// public string FullName { get { return FullNameCreator.FullName(this, false, null, null); } } /// public string ReflectionFullName { get { return FullNameCreator.FullName(this, true, null, null); } } /// public string AssemblyQualifiedName { get { return FullNameCreator.AssemblyQualifiedName(this, null, null); } } /// public IAssembly DefinitionAssembly { get { return FullNameCreator.DefinitionAssembly(this); } } /// public IScope Scope { get { return Module; } } /// public ITypeDefOrRef ScopeType { get { return this; } } /// /// Always returns false since a does not contain any /// or . /// public bool ContainsGenericParameter { get { return false; } } /// public ModuleDef Module { get { return FullNameCreator.OwnerModule(this); } } /// /// Gets/sets the owner module /// internal ModuleDef Module2 { get { if (!module2_isInitialized) InitializeModule2(); return module2; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif module2 = value; module2_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected ModuleDef module2; /// protected bool module2_isInitialized; void InitializeModule2() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (module2_isInitialized) return; module2 = GetModule2_NoLock(); module2_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual ModuleDef GetModule2_NoLock() { return null; } bool IIsTypeOrMethod.IsType { get { return true; } } bool IIsTypeOrMethod.IsMethod { get { return false; } } bool IMemberRef.IsField { get { return false; } } bool IMemberRef.IsTypeSpec { get { return false; } } bool IMemberRef.IsTypeRef { get { return false; } } bool IMemberRef.IsTypeDef { get { return true; } } bool IMemberRef.IsMethodSpec { get { return false; } } bool IMemberRef.IsMethodDef { get { return false; } } bool IMemberRef.IsMemberRef { get { return false; } } bool IMemberRef.IsFieldDef { get { return false; } } bool IMemberRef.IsPropertyDef { get { return false; } } bool IMemberRef.IsEventDef { get { return false; } } bool IMemberRef.IsGenericParam { get { return false; } } /// /// From column TypeDef.Flags /// public TypeAttributes Attributes { get { return (TypeAttributes)attributes; } set { attributes = (int)value; } } /// Attributes protected int attributes; /// /// From column TypeDef.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// From column TypeDef.Namespace /// public UTF8String Namespace { get { return @namespace; } set { @namespace = value; } } /// Name protected UTF8String @namespace; /// /// From column TypeDef.Extends /// public ITypeDefOrRef BaseType { get { if (!baseType_isInitialized) InitializeBaseType(); return baseType; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif baseType = value; baseType_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected ITypeDefOrRef baseType; /// protected bool baseType_isInitialized; void InitializeBaseType() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (baseType_isInitialized) return; baseType = GetBaseType_NoLock(); baseType_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual ITypeDefOrRef GetBaseType_NoLock() { return null; } /// Reset protected void ResetBaseType() { baseType_isInitialized = false; } /// /// From column TypeDef.FieldList /// public ThreadSafe.IList Fields { get { if (fields == null) InitializeFields(); return fields; } } /// protected LazyList fields; /// Initializes protected virtual void InitializeFields() { Interlocked.CompareExchange(ref fields, new LazyList(this), null); } /// /// From column TypeDef.MethodList /// public ThreadSafe.IList Methods { get { if (methods == null) InitializeMethods(); return methods; } } /// protected LazyList methods; /// Initializes protected virtual void InitializeMethods() { Interlocked.CompareExchange(ref methods, new LazyList(this), null); } /// public ThreadSafe.IList GenericParameters { get { if (genericParameters == null) InitializeGenericParameters(); return genericParameters; } } /// protected LazyList genericParameters; /// Initializes protected virtual void InitializeGenericParameters() { Interlocked.CompareExchange(ref genericParameters, new LazyList(this), null); } /// /// Gets the interfaces /// public ThreadSafe.IList Interfaces { get { if (interfaces == null) InitializeInterfaces(); return interfaces; } } /// protected ThreadSafe.IList interfaces; /// Initializes protected virtual void InitializeInterfaces() { Interlocked.CompareExchange(ref interfaces, ThreadSafeListCreator.Create(), null); } /// public ThreadSafe.IList DeclSecurities { get { if (declSecurities == null) InitializeDeclSecurities(); return declSecurities; } } /// protected ThreadSafe.IList declSecurities; /// Initializes protected virtual void InitializeDeclSecurities() { Interlocked.CompareExchange(ref declSecurities, ThreadSafeListCreator.Create(), null); } /// /// Gets/sets the class layout /// public ClassLayout ClassLayout { get { if (!classLayout_isInitialized) InitializeClassLayout(); return classLayout; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif classLayout = value; classLayout_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected ClassLayout classLayout; /// protected bool classLayout_isInitialized; void InitializeClassLayout() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (classLayout_isInitialized) return; classLayout = GetClassLayout_NoLock(); classLayout_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } ClassLayout GetOrCreateClassLayout() { var cl = ClassLayout; if (cl != null) return cl; Interlocked.CompareExchange(ref classLayout, new ClassLayoutUser(0, 0), null); return classLayout; } /// Called to initialize protected virtual ClassLayout GetClassLayout_NoLock() { return null; } /// public bool HasDeclSecurities { get { return DeclSecurities.Count > 0; } } /// /// Gets/sets the enclosing type. It's null if this isn't a nested class. /// public TypeDef DeclaringType { get { if (!declaringType2_isInitialized) InitializeDeclaringType2(); return declaringType2; } set { var currentDeclaringType = DeclaringType2; if (currentDeclaringType == value) return; if (currentDeclaringType != null) currentDeclaringType.NestedTypes.Remove(this); // Will set DeclaringType2 = null if (value != null) value.NestedTypes.Add(this); // Will set DeclaringType2 = value // Make sure this is clear. Will be set whenever it's inserted into ModulDef.Types Module2 = null; } } /// ITypeDefOrRef IMemberRef.DeclaringType { get { return DeclaringType; } } /// /// Called by and should normally not be called by any user /// code. Use instead. Only call this if you must set the /// declaring type without inserting it in the declaring type's method list. /// public TypeDef DeclaringType2 { get { if (!declaringType2_isInitialized) InitializeDeclaringType2(); return declaringType2; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif declaringType2 = value; declaringType2_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected TypeDef declaringType2; /// protected bool declaringType2_isInitialized; void InitializeDeclaringType2() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (declaringType2_isInitialized) return; declaringType2 = GetDeclaringType2_NoLock(); declaringType2_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual TypeDef GetDeclaringType2_NoLock() { return null; } /// /// Gets all the nested types /// public ThreadSafe.IList NestedTypes { get { if (nestedTypes == null) InitializeNestedTypes(); return nestedTypes; } } /// protected LazyList nestedTypes; /// Initializes protected virtual void InitializeNestedTypes() { Interlocked.CompareExchange(ref nestedTypes, new LazyList(this), null); } /// /// Gets all events /// public ThreadSafe.IList Events { get { if (events == null) InitializeEvents(); return events; } } /// protected LazyList events; /// Initializes protected virtual void InitializeEvents() { Interlocked.CompareExchange(ref events, new LazyList(this), null); } /// /// Gets all properties /// public ThreadSafe.IList Properties { get { if (properties == null) InitializeProperties(); return properties; } } /// protected LazyList properties; /// Initializes protected virtual void InitializeProperties() { Interlocked.CompareExchange(ref properties, new LazyList(this), null); } /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 3; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// /// true if there's at least one in /// public bool HasFields { get { return Fields.Count > 0; } } /// /// true if there's at least one in /// public bool HasMethods { get { return Methods.Count > 0; } } /// /// true if there's at least one in /// public bool HasGenericParameters { get { return GenericParameters.Count > 0; } } /// /// true if there's at least one in /// public bool HasEvents { get { return Events.Count > 0; } } /// /// true if there's at least one in /// public bool HasProperties { get { return Properties.Count > 0; } } /// /// true if there's at least one in /// public bool HasNestedTypes { get { return NestedTypes.Count > 0; } } /// /// true if there's at least one in /// public bool HasInterfaces { get { return Interfaces.Count > 0; } } /// /// true if is not null /// public bool HasClassLayout { get { return ClassLayout != null; } } /// /// Gets/sets the packing size. If you write to this property but /// is null, it will be created. The value is returned /// if is null. /// public ushort PackingSize { get { var cl = ClassLayout; return cl == null ? ushort.MaxValue : cl.PackingSize; } set { var cl = GetOrCreateClassLayout(); cl.PackingSize = value; } } /// /// Gets/sets the class size. If you write to this property but /// is null, it will be created. The value is returned /// if is null. /// public uint ClassSize { get { var cl = ClassLayout; return cl == null ? uint.MaxValue : cl.ClassSize; } set { var cl = GetOrCreateClassLayout(); cl.ClassSize = value; } } /// public bool IsValueType { get { // Don't include abstract since value types can be abstract without throwing at runtime if ((Attributes & (TypeAttributes.Sealed | TypeAttributes.ClassSemanticsMask)) != (TypeAttributes.Sealed | TypeAttributes.Class)) return false; var baseType = BaseType; if (baseType == null) return false; if (!baseType.DefinitionAssembly.IsCorLib()) return false; // PERF: Don't allocate a System.String by calling FullName etc. UTF8String baseName, baseNamespace; var baseTr = baseType as TypeRef; if (baseTr != null) { baseName = baseTr.Name; baseNamespace = baseTr.Namespace; } else { var baseTd = baseType as TypeDef; if (baseTd == null) return false; baseName = baseTd.Name; baseNamespace = baseTd.Namespace; } if (baseNamespace != systemString) return false; if (baseName != valueTypeString && baseName != enumString) return false; if (!DefinitionAssembly.IsCorLib()) return true; return !(Name == enumString && Namespace == systemString); } } static readonly UTF8String systemString = new UTF8String("System"); static readonly UTF8String enumString = new UTF8String("Enum"); static readonly UTF8String valueTypeString = new UTF8String("ValueType"); static readonly UTF8String multicastDelegateString = new UTF8String("MulticastDelegate"); /// /// true if it's an enum /// public bool IsEnum { get { // Don't include abstract since value types can be abstract without throwing at runtime if ((Attributes & (TypeAttributes.Sealed | TypeAttributes.ClassSemanticsMask)) != (TypeAttributes.Sealed | TypeAttributes.Class)) return false; var baseType = BaseType; if (baseType == null) return false; if (!baseType.DefinitionAssembly.IsCorLib()) return false; // PERF: Don't allocate a System.String by calling FullName etc. var baseTr = baseType as TypeRef; if (baseTr != null) return baseTr.Namespace == systemString && baseTr.Name == enumString; var baseTd = baseType as TypeDef; if (baseTd != null) return baseTd.Namespace == systemString && baseTd.Name == enumString; return false; } } /// /// true if it's a delegate (it derives from ) /// public bool IsDelegate { get { if ((Attributes & (TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.ClassSemanticsMask)) != (TypeAttributes.Sealed | TypeAttributes.Class)) return false; var baseType = BaseType; if (baseType == null) return false; if (!baseType.DefinitionAssembly.IsCorLib()) return false; // PERF: Don't allocate a System.String by calling FullName etc. var baseTr = baseType as TypeRef; if (baseTr != null) return baseTr.Namespace == systemString && baseTr.Name == multicastDelegateString; var baseTd = baseType as TypeDef; if (baseTd != null) return baseTd.Namespace == systemString && baseTd.Name == multicastDelegateString; return false; } } /// /// true if this is a nested type (it has a declaring type) /// public bool IsNested { get { return DeclaringType != null; } } /// public bool IsPrimitive { get { return this.IsPrimitive(); } } /// /// Modify property: = /// ( & ) | . /// /// Value to AND /// Value to OR void ModifyAttributes(TypeAttributes andMask, TypeAttributes 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 attributes = (attributes & (int)andMask) | (int)orMask; #endif } /// /// Set or clear flags in /// /// true if flags should be set, false if flags should /// be cleared /// Flags to set or clear void ModifyAttributes(bool set, TypeAttributes 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 visibility /// public TypeAttributes Visibility { get { return (TypeAttributes)attributes & TypeAttributes.VisibilityMask; } set { ModifyAttributes(~TypeAttributes.VisibilityMask, value & TypeAttributes.VisibilityMask); } } /// /// true if is set /// public bool IsNotPublic { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic; } } /// /// true if is set /// public bool IsPublic { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public; } } /// /// true if is set /// public bool IsNestedPublic { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic; } } /// /// true if is set /// public bool IsNestedPrivate { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate; } } /// /// true if is set /// public bool IsNestedFamily { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamily; } } /// /// true if is set /// public bool IsNestedAssembly { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedAssembly; } } /// /// true if is set /// public bool IsNestedFamilyAndAssembly { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamANDAssem; } } /// /// true if is set /// public bool IsNestedFamilyOrAssembly { get { return ((TypeAttributes)attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamORAssem; } } /// /// Gets/sets the layout /// public TypeAttributes Layout { get { return (TypeAttributes)attributes & TypeAttributes.LayoutMask; } set { ModifyAttributes(~TypeAttributes.LayoutMask, value & TypeAttributes.LayoutMask); } } /// /// true if is set /// public bool IsAutoLayout { get { return ((TypeAttributes)attributes & TypeAttributes.LayoutMask) == TypeAttributes.AutoLayout; } } /// /// true if is set /// public bool IsSequentialLayout { get { return ((TypeAttributes)attributes & TypeAttributes.LayoutMask) == TypeAttributes.SequentialLayout; } } /// /// true if is set /// public bool IsExplicitLayout { get { return ((TypeAttributes)attributes & TypeAttributes.LayoutMask) == TypeAttributes.ExplicitLayout; } } /// /// Gets/sets the bit /// public bool IsInterface { get { return ((TypeAttributes)attributes & TypeAttributes.Interface) != 0; } set { ModifyAttributes(value, TypeAttributes.Interface); } } /// /// Gets/sets the bit /// public bool IsClass { get { return ((TypeAttributes)attributes & TypeAttributes.Interface) == 0; } set { ModifyAttributes(!value, TypeAttributes.Interface); } } /// /// Gets/sets the bit /// public bool IsAbstract { get { return ((TypeAttributes)attributes & TypeAttributes.Abstract) != 0; } set { ModifyAttributes(value, TypeAttributes.Abstract); } } /// /// Gets/sets the bit /// public bool IsSealed { get { return ((TypeAttributes)attributes & TypeAttributes.Sealed) != 0; } set { ModifyAttributes(value, TypeAttributes.Sealed); } } /// /// Gets/sets the bit /// public bool IsSpecialName { get { return ((TypeAttributes)attributes & TypeAttributes.SpecialName) != 0; } set { ModifyAttributes(value, TypeAttributes.SpecialName); } } /// /// Gets/sets the bit /// public bool IsImport { get { return ((TypeAttributes)attributes & TypeAttributes.Import) != 0; } set { ModifyAttributes(value, TypeAttributes.Import); } } /// /// Gets/sets the bit /// public bool IsSerializable { get { return ((TypeAttributes)attributes & TypeAttributes.Serializable) != 0; } set { ModifyAttributes(value, TypeAttributes.Serializable); } } /// /// Gets/sets the bit /// public bool IsWindowsRuntime { get { return ((TypeAttributes)attributes & TypeAttributes.WindowsRuntime) != 0; } set { ModifyAttributes(value, TypeAttributes.WindowsRuntime); } } /// /// Gets/sets the string format /// public TypeAttributes StringFormat { get { return (TypeAttributes)attributes & TypeAttributes.StringFormatMask; } set { ModifyAttributes(~TypeAttributes.StringFormatMask, value & TypeAttributes.StringFormatMask); } } /// /// true if is set /// public bool IsAnsiClass { get { return ((TypeAttributes)attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AnsiClass; } } /// /// true if is set /// public bool IsUnicodeClass { get { return ((TypeAttributes)attributes & TypeAttributes.StringFormatMask) == TypeAttributes.UnicodeClass; } } /// /// true if is set /// public bool IsAutoClass { get { return ((TypeAttributes)attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AutoClass; } } /// /// true if is set /// public bool IsCustomFormatClass { get { return ((TypeAttributes)attributes & TypeAttributes.StringFormatMask) == TypeAttributes.CustomFormatClass; } } /// /// Gets/sets the bit /// public bool IsBeforeFieldInit { get { return ((TypeAttributes)attributes & TypeAttributes.BeforeFieldInit) != 0; } set { ModifyAttributes(value, TypeAttributes.BeforeFieldInit); } } /// /// Gets/sets the bit /// public bool IsForwarder { get { return ((TypeAttributes)attributes & TypeAttributes.Forwarder) != 0; } set { ModifyAttributes(value, TypeAttributes.Forwarder); } } /// /// Gets/sets the bit /// public bool IsRuntimeSpecialName { get { return ((TypeAttributes)attributes & TypeAttributes.RTSpecialName) != 0; } set { ModifyAttributes(value, TypeAttributes.RTSpecialName); } } /// /// Gets/sets the bit /// public bool HasSecurity { get { return ((TypeAttributes)attributes & TypeAttributes.HasSecurity) != 0; } set { ModifyAttributes(value, TypeAttributes.HasSecurity); } } /// /// true if this is the global (aka. <Module>) type /// public bool IsGlobalModuleType { get { var mod = Module; return mod != null && mod.GlobalType == this; } } /// /// Gets a list of all nested types and all their nested types /// public IEnumerable GetTypes() { return AllTypesHelper.Types(NestedTypes); } /// /// Gets an enum's underlying type or null if none. Should only be called /// if this is an enum. /// public TypeSig GetEnumUnderlyingType() { foreach (var field in Fields.GetSafeEnumerable()) { if (!field.IsLiteral && !field.IsStatic) { var fieldSig = field.FieldSig; if (fieldSig != null) return fieldSig.Type; } } return null; } /// /// Resolves a method or a field. (owner type) is ignored when /// resolving the method/field. Private scope methods/fields are not returned. /// /// A method/field reference /// A or a instance or null /// if it couldn't be resolved. public IMemberForwarded Resolve(MemberRef memberRef) { return Resolve(memberRef, 0); } /// /// Resolves a method or a field. (owner type) is ignored when /// resolving the method/field. /// /// A method/field reference /// Method/field signature comparison options /// A or a instance or null /// if it couldn't be resolved. public IMemberForwarded Resolve(MemberRef memberRef, SigComparerOptions options) { if (memberRef == null) return null; var methodSig = memberRef.MethodSig; if (methodSig != null) return FindMethodCheckBaseType(memberRef.Name, methodSig, options, memberRef.Module); var fieldSig = memberRef.FieldSig; if (fieldSig != null) return FindFieldCheckBaseType(memberRef.Name, fieldSig, options, memberRef.Module); return null; } /// /// Finds a method. Private scope methods are not returned. /// /// Method name /// Method signature /// The first method that matches or null if none found public MethodDef FindMethod(UTF8String name, MethodSig sig) { return FindMethod(name, sig, 0, null); } /// /// Finds a method /// /// Method name /// Method signature /// Method signature comparison options /// The first method that matches or null if none found public MethodDef FindMethod(UTF8String name, MethodSig sig, SigComparerOptions options) { return FindMethod(name, sig, options, null); } /// /// Finds a method /// /// Method name /// Method signature /// Method signature comparison options /// The module that needs to find the method or null /// The first method that matches or null if none found public MethodDef FindMethod(UTF8String name, MethodSig sig, SigComparerOptions options, ModuleDef sourceModule) { if (UTF8String.IsNull(name) || sig == null) return null; var comparer = new SigComparer(options, sourceModule); bool allowPrivateScope = (options & SigComparerOptions.PrivateScopeMethodIsComparable) != 0; foreach (var method in Methods.GetSafeEnumerable()) { if (!allowPrivateScope && method.IsPrivateScope) continue; if (!UTF8String.Equals(method.Name, name)) continue; if (comparer.Equals(method.MethodSig, sig)) return method; } return null; } /// /// Finds a method by name /// /// Name of method /// The or null if not found public MethodDef FindMethod(UTF8String name) { foreach (var method in Methods.GetSafeEnumerable()) { if (UTF8String.Equals(method.Name, name)) return method; } return null; } /// /// Finds all methods by name /// /// Name of method /// All methods with that name public IEnumerable FindMethods(UTF8String name) { foreach (var method in Methods.GetSafeEnumerable()) { if (UTF8String.Equals(method.Name, name)) yield return method; } } /// /// Finds the class constructor (aka type initializer). It's the method named .cctor /// /// The class constructor or null if none found public MethodDef FindStaticConstructor() { return Methods.ExecuteLocked(null, (tsList, arg) => FindStaticConstructor_NoMethodsLock()); } MethodDef FindStaticConstructor_NoMethodsLock() { foreach (var method in Methods.GetEnumerable_NoLock()) { if (method.IsStaticConstructor) return method; } return null; } /// /// Finds the class constructor (aka type initializer). It's the method named .cctor. /// If it doesn't exist, it is created, inserted into and returned. /// The created .cctor will have just one RET instruction. /// /// The class constructor public MethodDef FindOrCreateStaticConstructor() { var cctor = FindStaticConstructor(); if (cctor != null) return cctor; var implFlags = MethodImplAttributes.IL | MethodImplAttributes.Managed; var flags = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; var module = Module; cctor = module.UpdateRowId(new MethodDefUser(MethodDef.StaticConstructorName, MethodSig.CreateStatic(module.CorLibTypes.Void), implFlags, flags)); var body = new CilBody(); body.InitLocals = true; body.MaxStack = 8; body.Instructions.Add(OpCodes.Ret.ToInstruction()); cctor.Body = body; return Methods.ExecuteLocked(cctor, (tsList, cctor2) => { var cctor3 = FindStaticConstructor_NoMethodsLock(); if (cctor3 != null) return cctor3; tsList.Add_NoLock(cctor2); return cctor2; }); } /// /// Finds all instance constructors (not class constructors) /// /// All instance constructors public IEnumerable FindInstanceConstructors() { foreach (var method in Methods.GetSafeEnumerable()) { if (method.IsInstanceConstructor) yield return method; } } /// /// Finds all static and instance constructors /// /// All static and instance constructors public IEnumerable FindConstructors() { foreach (var method in Methods.GetSafeEnumerable()) { if (method.IsConstructor) yield return method; } } /// /// Finds the default instance constructor (the one with no arguments) /// /// The default instance constructor or null if none public MethodDef FindDefaultConstructor() { foreach (var method in Methods.GetSafeEnumerable()) { if (!method.IsInstanceConstructor) continue; var sig = method.MethodSig; if (sig != null && sig.Params.Count == 0) return method; } return null; } /// /// Finds a field. Private scope fields are not returned. /// /// Field name /// Field signature /// The first field that matches or null if none found public FieldDef FindField(UTF8String name, FieldSig sig) { return FindField(name, sig, 0, null); } /// /// Finds a field /// /// Field name /// Field signature /// Field signature comparison options /// The first field that matches or null if none found public FieldDef FindField(UTF8String name, FieldSig sig, SigComparerOptions options) { return FindField(name, sig, options, null); } /// /// Finds a field /// /// Field name /// Field signature /// Field signature comparison options /// The module that needs to find the field or null /// The first field that matches or null if none found public FieldDef FindField(UTF8String name, FieldSig sig, SigComparerOptions options, ModuleDef sourceModule) { if (UTF8String.IsNull(name) || sig == null) return null; var comparer = new SigComparer(options, sourceModule); bool allowPrivateScope = (options & SigComparerOptions.PrivateScopeFieldIsComparable) != 0; foreach (var field in Fields.GetSafeEnumerable()) { if (!allowPrivateScope && field.IsPrivateScope) continue; if (!UTF8String.Equals(field.Name, name)) continue; if (comparer.Equals(field.FieldSig, sig)) return field; } return null; } /// /// Finds a field by name /// /// Name of field /// The or null if not found public FieldDef FindField(UTF8String name) { foreach (var field in Fields.GetSafeEnumerable()) { if (UTF8String.Equals(field.Name, name)) return field; } return null; } /// /// Finds all fields by name /// /// Name of field /// All fields with that name public IEnumerable FindFields(UTF8String name) { foreach (var field in Fields.GetSafeEnumerable()) { if (UTF8String.Equals(field.Name, name)) yield return field; } } /// /// Finds an event /// /// Name of event /// Type of event /// A or null if not found public EventDef FindEvent(UTF8String name, IType type) { return FindEvent(name, type, 0, null); } /// /// Finds an event /// /// Name of event /// Type of event /// Event type comparison options /// A or null if not found public EventDef FindEvent(UTF8String name, IType type, SigComparerOptions options) { return FindEvent(name, type, options, null); } /// /// Finds an event /// /// Name of event /// Type of event /// Event type comparison options /// The module that needs to find the event or null /// A or null if not found public EventDef FindEvent(UTF8String name, IType type, SigComparerOptions options, ModuleDef sourceModule) { if (UTF8String.IsNull(name) || type == null) return null; var comparer = new SigComparer(options, sourceModule); foreach (var @event in Events.GetSafeEnumerable()) { if (!UTF8String.Equals(@event.Name, name)) continue; if (comparer.Equals(@event.EventType, type)) return @event; } return null; } /// /// Finds an event by name /// /// Name of event /// The or null if not found public EventDef FindEvent(UTF8String name) { foreach (var @event in Events.GetSafeEnumerable()) { if (UTF8String.Equals(@event.Name, name)) return @event; } return null; } /// /// Finds all events by name /// /// Name of event /// All events with that name public IEnumerable FindEvents(UTF8String name) { foreach (var @event in Events.GetSafeEnumerable()) { if (UTF8String.Equals(@event.Name, name)) yield return @event; } } /// /// Finds a property /// /// Name of property /// Property signature /// A or null if not found public PropertyDef FindProperty(UTF8String name, CallingConventionSig propSig) { return FindProperty(name, propSig, 0, null); } /// /// Finds a property /// /// Name of property /// Property signature /// Property signature comparison options /// A or null if not found public PropertyDef FindProperty(UTF8String name, CallingConventionSig propSig, SigComparerOptions options) { return FindProperty(name, propSig, options, null); } /// /// Finds a property /// /// Name of property /// Property signature /// Property signature comparison options /// The module that needs to find the property or null /// A or null if not found public PropertyDef FindProperty(UTF8String name, CallingConventionSig propSig, SigComparerOptions options, ModuleDef sourceModule) { if (UTF8String.IsNull(name) || propSig == null) return null; var comparer = new SigComparer(options, sourceModule); foreach (var prop in Properties.GetSafeEnumerable()) { if (!UTF8String.Equals(prop.Name, name)) continue; if (comparer.Equals(prop.Type, propSig)) return prop; } return null; } /// /// Finds a prop by name /// /// Name of prop /// The or null if not found public PropertyDef FindProperty(UTF8String name) { foreach (var prop in Properties.GetSafeEnumerable()) { if (UTF8String.Equals(prop.Name, name)) return prop; } return null; } /// /// Finds all props by name /// /// Name of prop /// All props with that name public IEnumerable FindProperties(UTF8String name) { foreach (var prop in Properties.GetSafeEnumerable()) { if (UTF8String.Equals(prop.Name, name)) yield return prop; } } /// /// Finds a method by checking this type or any of its base types /// /// Method name /// Method signature /// The method or null if it wasn't found public MethodDef FindMethodCheckBaseType(UTF8String name, MethodSig sig) { return FindMethodCheckBaseType(name, sig, 0, null); } /// /// Finds a method by checking this type or any of its base types /// /// Method name /// Method signature /// Method signature comparison options /// The method or null if it wasn't found public MethodDef FindMethodCheckBaseType(UTF8String name, MethodSig sig, SigComparerOptions options) { return FindMethodCheckBaseType(name, sig, options, null); } /// /// Finds a method by checking this type or any of its base types /// /// Method name /// Method signature /// Method signature comparison options /// The module that needs to find the method or null /// The method or null if it wasn't found public MethodDef FindMethodCheckBaseType(UTF8String name, MethodSig sig, SigComparerOptions options, ModuleDef sourceModule) { var td = this; while (td != null) { var md = td.FindMethod(name, sig, options, sourceModule); if (md != null) return md; td = td.BaseType.ResolveTypeDef(); } return null; } /// /// Finds a method by checking this type or any of its base types /// /// Method name /// The method or null if it wasn't found public MethodDef FindMethodCheckBaseType(UTF8String name) { var td = this; while (td != null) { var md = td.FindMethod(name); if (md != null) return md; td = td.BaseType.ResolveTypeDef(); } return null; } /// /// Finds a field by checking this type or any of its base types /// /// Field name /// Field signature /// The field or null if it wasn't found public FieldDef FindFieldCheckBaseType(UTF8String name, FieldSig sig) { return FindFieldCheckBaseType(name, sig, 0, null); } /// /// Finds a field by checking this type or any of its base types /// /// Field name /// Field signature /// Field signature comparison options /// The field or null if it wasn't found public FieldDef FindFieldCheckBaseType(UTF8String name, FieldSig sig, SigComparerOptions options) { return FindFieldCheckBaseType(name, sig, options, null); } /// /// Finds a field by checking this type or any of its base types /// /// Field name /// Field signature /// Field signature comparison options /// The module that needs to find the field or null /// The field or null if it wasn't found public FieldDef FindFieldCheckBaseType(UTF8String name, FieldSig sig, SigComparerOptions options, ModuleDef sourceModule) { var td = this; while (td != null) { var fd = td.FindField(name, sig, options, sourceModule); if (fd != null) return fd; td = td.BaseType.ResolveTypeDef(); } return null; } /// /// Finds a field by checking this type or any of its base types /// /// Field name /// The field or null if it wasn't found public FieldDef FindFieldCheckBaseType(UTF8String name) { var td = this; while (td != null) { var fd = td.FindField(name); if (fd != null) return fd; td = td.BaseType.ResolveTypeDef(); } return null; } /// /// Finds an event by checking this type or any of its base types /// /// Event name /// Event type /// The event or null if it wasn't found public EventDef FindEventCheckBaseType(UTF8String name, ITypeDefOrRef eventType) { var td = this; while (td != null) { var ed = td.FindEvent(name, eventType); if (ed != null) return ed; td = td.BaseType.ResolveTypeDef(); } return null; } /// /// Finds an event by checking this type or any of its base types /// /// Event name /// The event or null if it wasn't found public EventDef FindEventCheckBaseType(UTF8String name) { var td = this; while (td != null) { var ed = td.FindEvent(name); if (ed != null) return ed; td = td.BaseType.ResolveTypeDef(); } return null; } /// /// Finds a property by checking this type or any of its base types /// /// Property name /// Property signature /// The property or null if it wasn't found public PropertyDef FindPropertyCheckBaseType(UTF8String name, PropertySig sig) { return FindPropertyCheckBaseType(name, sig, 0, null); } /// /// Finds a property by checking this type or any of its base types /// /// Property name /// Property signature /// Property signature comparison options /// The property or null if it wasn't found public PropertyDef FindPropertyCheckBaseType(UTF8String name, PropertySig sig, SigComparerOptions options) { return FindPropertyCheckBaseType(name, sig, options, null); } /// /// Finds a property by checking this type or any of its base types /// /// Property name /// Property signature /// Property signature comparison options /// The module that needs to find the property or null /// The property or null if it wasn't found public PropertyDef FindPropertyCheckBaseType(UTF8String name, PropertySig sig, SigComparerOptions options, ModuleDef sourceModule) { var td = this; while (td != null) { var pd = td.FindProperty(name, sig, options, sourceModule); if (pd != null) return pd; td = td.BaseType.ResolveTypeDef(); } return null; } /// /// Finds a property by checking this type or any of its base types /// /// Property name /// The property or null if it wasn't found public PropertyDef FindPropertyCheckBaseType(UTF8String name) { var td = this; while (td != null) { var pd = td.FindProperty(name); if (pd != null) return pd; td = td.BaseType.ResolveTypeDef(); } return null; } /// /// Removes a method from this type. It also removes it from any properties and events. /// /// The method to remove public void Remove(MethodDef method) { Remove(method, false); } /// /// Removes a method from this type. It also removes it from any properties and events. /// /// The method to remove /// true if we should remove all /// empty properties and events. public void Remove(MethodDef method, bool removeEmptyPropertiesEvents) { if (method == null) return; foreach (var prop in Properties.GetSafeEnumerable()) { prop.GetMethods.Remove(method); prop.SetMethods.Remove(method); prop.OtherMethods.Remove(method); } foreach (var evt in Events.GetSafeEnumerable()) { if (evt.AddMethod == method) evt.AddMethod = null; if (evt.RemoveMethod == method) evt.RemoveMethod = null; if (evt.InvokeMethod == method) evt.InvokeMethod = null; evt.OtherMethods.Remove(method); } if (removeEmptyPropertiesEvents) { RemoveEmptyProperties(); RemoveEmptyEvents(); } Methods.Remove(method); } void RemoveEmptyProperties() { Properties.IterateAllReverse((tsList, index, value) => { if (value.IsEmpty) tsList.RemoveAt_NoLock(index); }); } void RemoveEmptyEvents() { Events.IterateAllReverse((tsList, index, value) => { if (value.IsEmpty) tsList.RemoveAt_NoLock(index); }); } /// void IListListener.OnLazyAdd(int index, ref FieldDef value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref FieldDef value) { #if DEBUG if (value.DeclaringType != this) throw new InvalidOperationException("Added field's DeclaringType != this"); #endif } /// void IListListener.OnAdd(int index, FieldDef value) { if (value.DeclaringType != null) throw new InvalidOperationException("Field is already owned by another type. Set DeclaringType to null first."); value.DeclaringType2 = this; } /// void IListListener.OnRemove(int index, FieldDef value) { value.DeclaringType2 = null; } /// void IListListener.OnResize(int index) { } /// void IListListener.OnClear() { foreach (var field in Fields.GetEnumerable_NoLock()) field.DeclaringType2 = null; } /// void IListListener.OnLazyAdd(int index, ref MethodDef value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref MethodDef value) { #if DEBUG if (value.DeclaringType != this) throw new InvalidOperationException("Added method's DeclaringType != this"); #endif } /// void IListListener.OnAdd(int index, MethodDef value) { if (value.DeclaringType != null) throw new InvalidOperationException("Method is already owned by another type. Set DeclaringType to null first."); value.DeclaringType2 = this; value.Parameters.UpdateThisParameterType(this); } /// void IListListener.OnRemove(int index, MethodDef value) { value.DeclaringType2 = null; value.Parameters.UpdateThisParameterType(null); } /// void IListListener.OnResize(int index) { } /// void IListListener.OnClear() { foreach (var method in Methods.GetEnumerable_NoLock()) { method.DeclaringType2 = null; method.Parameters.UpdateThisParameterType(null); } } /// void IListListener.OnLazyAdd(int index, ref TypeDef value) { #if DEBUG if (value.Module2 != null) throw new InvalidOperationException("Added nested type's Module != null"); if (value.DeclaringType != this) throw new InvalidOperationException("Added nested type's DeclaringType != this"); #endif } /// void IListListener.OnAdd(int index, TypeDef value) { if (value.DeclaringType != null) throw new InvalidOperationException("Nested type is already owned by another type. Set DeclaringType to null first."); if (value.Module != null) throw new InvalidOperationException("Type is already owned by another module. Remove it from that module's type list."); value.DeclaringType2 = this; } /// void IListListener.OnRemove(int index, TypeDef value) { value.DeclaringType2 = null; value.Module2 = null; } /// void IListListener.OnResize(int index) { } /// void IListListener.OnClear() { foreach (var type in NestedTypes.GetEnumerable_NoLock()) type.DeclaringType2 = null; } /// void IListListener.OnLazyAdd(int index, ref EventDef value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref EventDef value) { #if DEBUG if (value.DeclaringType != this) throw new InvalidOperationException("Added event's DeclaringType != this"); #endif } /// void IListListener.OnAdd(int index, EventDef value) { if (value.DeclaringType != null) throw new InvalidOperationException("Event is already owned by another type. Set DeclaringType to null first."); value.DeclaringType2 = this; } /// void IListListener.OnRemove(int index, EventDef value) { value.DeclaringType2 = null; } /// void IListListener.OnResize(int index) { } /// void IListListener.OnClear() { foreach (var @event in Events.GetEnumerable_NoLock()) @event.DeclaringType2 = null; } /// void IListListener.OnLazyAdd(int index, ref PropertyDef value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref PropertyDef value) { #if DEBUG if (value.DeclaringType != this) throw new InvalidOperationException("Added property's DeclaringType != this"); #endif } /// void IListListener.OnAdd(int index, PropertyDef value) { if (value.DeclaringType != null) throw new InvalidOperationException("Property is already owned by another type. Set DeclaringType to null first."); value.DeclaringType2 = this; } /// void IListListener.OnRemove(int index, PropertyDef value) { value.DeclaringType2 = null; } /// void IListListener.OnResize(int index) { } /// void IListListener.OnClear() { foreach (var prop in Properties.GetEnumerable_NoLock()) prop.DeclaringType2 = null; } /// void IListListener.OnLazyAdd(int index, ref GenericParam value) { OnLazyAdd2(index, ref value); } internal virtual void OnLazyAdd2(int index, ref GenericParam value) { #if DEBUG if (value.Owner != this) throw new InvalidOperationException("Added generic param's Owner != this"); #endif } /// void IListListener.OnAdd(int index, GenericParam value) { if (value.Owner != null) throw new InvalidOperationException("Generic param is already owned by another type/method. Set Owner to null first."); value.Owner = this; } /// void IListListener.OnRemove(int index, GenericParam value) { value.Owner = null; } /// void IListListener.OnResize(int index) { } /// void IListListener.OnClear() { foreach (var gp in GenericParameters.GetEnumerable_NoLock()) gp.Owner = null; } /// /// Gets all fields named /// /// Field name /// A list of 0 or more fields with name public IList GetFields(UTF8String name) { var fields = new List(); foreach (var field in Fields.GetSafeEnumerable()) { if (field.Name == name) fields.Add(field); } return fields; } /// /// Gets the first field named /// /// Field name /// The field or null if none found public FieldDef GetField(UTF8String name) { foreach (var field in Fields.GetSafeEnumerable()) { if (field.Name == name) return field; } return null; } internal static bool GetClassSize(TypeDef td, out uint size) { size = 0; if (td == null) return false; if (!td.IsValueType) return false; // Not supported by us if (!td.IsSequentialLayout && !td.IsExplicitLayout) { if (td.Fields.Count != 1) return false; var fd = td.Fields.Get(0, null); if (fd == null) return false; return fd.GetFieldSize(out size); } var classLayout = td.ClassLayout; if (classLayout == null) return false; uint classSize = classLayout.ClassSize; if (classSize != 0) { size = classSize; return true; } // Not supported by us return false; } /// /// FInd a method implementation method /// /// Method /// protected MethodDef FindMethodImplMethod(IMethodDefOrRef mdr) { // Check common case first var md = mdr as MethodDef; if (md != null) return md; // Must be a member ref var mr = mdr as MemberRef; if (mr == null) return null; // If Class is MethodDef, then it should be a vararg method var parent = mr.Class; md = parent as MethodDef; if (md != null) return md; // If it's a TypeSpec, it must be a generic instance type for (int i = 0; i < 10; i++) { var ts = parent as TypeSpec; if (ts == null) break; var gis = ts.TypeSig as GenericInstSig; if (gis == null || gis.GenericType == null) return null; parent = gis.GenericType.TypeDefOrRef; } var td = parent as TypeDef; if (td == null) { // If it's a TypeRef, resolve it as if it is a reference to a type in the // current module, even if its ResolutionScope happens to be some other // assembly/module (that's what the CLR does) var tr = parent as TypeRef; if (tr != null && Module != null) td = Module.Find(tr); } if (td == null) return null; return td.FindMethod(mr.Name, mr.MethodSig); } /// public override string ToString() { return FullName; } } /// /// A TypeDef row created by the user and not present in the original .NET file /// public class TypeDefUser : TypeDef { /// /// Constructor /// /// Name public TypeDefUser(UTF8String name) : this(null, name, null) { } /// /// Constructor /// /// Namespace /// Name public TypeDefUser(UTF8String @namespace, UTF8String name) : this(@namespace, name, null) { } /// /// Constructor /// /// Name /// Base class or null if it's an interface public TypeDefUser(UTF8String name, ITypeDefOrRef baseType) : this(null, name, baseType) { } /// /// Constructor /// /// Namespace /// Name /// Base class or null if it's an interface public TypeDefUser(UTF8String @namespace, UTF8String name, ITypeDefOrRef baseType) { this.fields = new LazyList(this); this.methods = new LazyList(this); this.genericParameters = new LazyList(this); this.nestedTypes = new LazyList(this); this.events = new LazyList(this); this.properties = new LazyList(this); this.@namespace = @namespace; this.name = name; this.baseType = baseType; this.baseType_isInitialized = true; } } /// /// Created from a row in the TypeDef table /// sealed class TypeDefMD : TypeDef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; readonly uint extendsCodedToken; Dictionary> methodRidToOverrides; /// public uint OrigRid { get { return origRid; } } /// protected override ITypeDefOrRef GetBaseType_NoLock() { return readerModule.ResolveTypeDefOrRef(extendsCodedToken, new GenericParamContext(this)); } /// protected override void InitializeFields() { var list = readerModule.MetaData.GetFieldRidList(origRid); var tmp = new LazyList((int)list.Length, this, list, (list2, index) => readerModule.ResolveField(((RidList)list2)[index])); Interlocked.CompareExchange(ref fields, tmp, null); } /// protected override void InitializeMethods() { var list = readerModule.MetaData.GetMethodRidList(origRid); var tmp = new LazyList((int)list.Length, this, list, (list2, index) => readerModule.ResolveMethod(((RidList)list2)[index])); Interlocked.CompareExchange(ref methods, tmp, null); } /// protected override void InitializeGenericParameters() { var list = readerModule.MetaData.GetGenericParamRidList(Table.TypeDef, origRid); var tmp = new LazyList((int)list.Length, this, list, (list2, index) => readerModule.ResolveGenericParam(((RidList)list2)[index])); Interlocked.CompareExchange(ref genericParameters, tmp, null); } /// protected override void InitializeInterfaces() { var list = readerModule.MetaData.GetInterfaceImplRidList(origRid); var tmp = new LazyList((int)list.Length, list, (list2, index) => readerModule.ResolveInterfaceImpl(((RidList)list2)[index], new GenericParamContext(this))); Interlocked.CompareExchange(ref interfaces, tmp, null); } /// protected override void InitializeDeclSecurities() { var list = readerModule.MetaData.GetDeclSecurityRidList(Table.TypeDef, origRid); var tmp = new LazyList((int)list.Length, list, (list2, index) => readerModule.ResolveDeclSecurity(((RidList)list2)[index])); Interlocked.CompareExchange(ref declSecurities, tmp, null); } /// protected override ClassLayout GetClassLayout_NoLock() { return readerModule.ResolveClassLayout(readerModule.MetaData.GetClassLayoutRid(origRid)); } /// protected override TypeDef GetDeclaringType2_NoLock() { uint enclosingClass = readerModule.TablesStream.ReadNestedClassRow2(readerModule.MetaData.GetNestedClassRid(origRid)); return enclosingClass == 0 ? null : readerModule.ResolveTypeDef(enclosingClass); } TypeDef DeclaringType2_NoLock { get { if (!declaringType2_isInitialized) { declaringType2 = GetDeclaringType2_NoLock(); declaringType2_isInitialized = true; } return declaringType2; } } /// protected override void InitializeEvents() { var mapRid = readerModule.MetaData.GetEventMapRid(origRid); var list = readerModule.MetaData.GetEventRidList(mapRid); var tmp = new LazyList((int)list.Length, this, list, (list2, index) => readerModule.ResolveEvent(((RidList)list2)[index])); Interlocked.CompareExchange(ref events, tmp, null); } /// protected override void InitializeProperties() { var mapRid = readerModule.MetaData.GetPropertyMapRid(origRid); var list = readerModule.MetaData.GetPropertyRidList(mapRid); var tmp = new LazyList((int)list.Length, this, list, (list2, index) => readerModule.ResolveProperty(((RidList)list2)[index])); Interlocked.CompareExchange(ref properties, tmp, null); } /// protected override void InitializeNestedTypes() { var list = readerModule.MetaData.GetNestedClassRidList(origRid); var tmp = new LazyList((int)list.Length, this, list, (list2, index) => readerModule.ResolveTypeDef(((RidList)list2)[index])); Interlocked.CompareExchange(ref nestedTypes, tmp, null); } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.TypeDef, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(this), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// protected override ModuleDef GetModule2_NoLock() { return DeclaringType2_NoLock != null ? null : readerModule; } /// /// Constructor /// /// The module which contains this TypeDef row /// Row ID /// If is null /// If is invalid public TypeDefMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.TypeDefTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("TypeDef rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; uint name, @namespace; extendsCodedToken = readerModule.TablesStream.ReadTypeDefRow(origRid, out this.attributes, out name, out @namespace); this.name = readerModule.StringsStream.ReadNoNull(name); this.@namespace = readerModule.StringsStream.ReadNoNull(@namespace); } /// /// Gets all methods overrides /// /// The method /// Generic parameter context /// A list (possibly empty) of all methods overrides internal ThreadSafe.IList GetMethodOverrides(MethodDefMD method, GenericParamContext gpContext) { if (method == null) return ThreadSafeListCreator.Create(); if (methodRidToOverrides == null) InitializeMethodOverrides(); ThreadSafe.IList overrides; if (methodRidToOverrides.TryGetValue(method.OrigRid, out overrides)) { var newList = ThreadSafeListCreator.Create(overrides.Count); for (int i = 0; i < overrides.Count; i++) { var ovr = overrides[i]; var newMethodBody = (IMethodDefOrRef)readerModule.ResolveToken(ovr.MethodBodyToken, gpContext); var newMethodDeclaration = (IMethodDefOrRef)readerModule.ResolveToken(ovr.MethodDeclarationToken, gpContext); newList.Add(new MethodOverride(newMethodBody, newMethodDeclaration)); } return newList; } return ThreadSafeListCreator.Create(); } struct MethodOverrideTokens { public readonly uint MethodBodyToken; public readonly uint MethodDeclarationToken; public MethodOverrideTokens(uint methodBodyToken, uint methodDeclarationToken) { this.MethodBodyToken = methodBodyToken; this.MethodDeclarationToken = methodDeclarationToken; } } void InitializeMethodOverrides() { var newMethodRidToOverrides = new Dictionary>(); var ridList = readerModule.MetaData.GetMethodImplRidList(origRid); for (uint i = 0; i < ridList.Length; i++) { uint methodBodyToken; uint methodDeclToken = readerModule.TablesStream.ReadMethodImplRow(ridList[i], out methodBodyToken); var methodBody = readerModule.ResolveMethodDefOrRef(methodBodyToken); var methodDecl = readerModule.ResolveMethodDefOrRef(methodDeclToken); if (methodBody == null || methodDecl == null) continue; // Should only happen if some obfuscator added invalid metadata // Find the real method. This is usually methodBody since it's usually a // MethodDef. The CLR only allows method bodies in the current type, and // so shall we. var method = FindMethodImplMethod(methodBody); if (method == null || method.DeclaringType != this) continue; ThreadSafe.IList overrides; uint rid = method.Rid; if (!newMethodRidToOverrides.TryGetValue(rid, out overrides)) newMethodRidToOverrides[rid] = overrides = ThreadSafeListCreator.Create(); overrides.Add(new MethodOverrideTokens(methodBody.MDToken.Raw, methodDecl.MDToken.Raw)); } Interlocked.CompareExchange(ref methodRidToOverrides, newMethodRidToOverrides, null); } /// /// Initializes all . Only those s /// that are property or event handlers get updated. /// internal void InitializeMethodSemanticsAttributes() { var mapRid = readerModule.MetaData.GetPropertyMapRid(origRid); var list = readerModule.MetaData.GetPropertyRidList(mapRid); for (uint i = 0; i < list.Length; i++) { var ridList = readerModule.MetaData.GetMethodSemanticsRidList(Table.Property, list[i]); for (uint j = 0; j < ridList.Length; j++) { MethodSemanticsAttributes semantics; uint methodToken = readerModule.TablesStream.ReadMethodSemanticsRow(ridList[j], out semantics); var method = readerModule.ResolveMethod(methodToken); if (method == null) continue; Interlocked.CompareExchange(ref method.semAttrs, (int)semantics | MethodDef.SEMATTRS_INITD, 0); } } mapRid = readerModule.MetaData.GetEventMapRid(origRid); list = readerModule.MetaData.GetEventRidList(mapRid); for (uint i = 0; i < list.Length; i++) { var ridList = readerModule.MetaData.GetMethodSemanticsRidList(Table.Event, list[i]); for (uint j = 0; j < ridList.Length; j++) { MethodSemanticsAttributes semantics; uint methodToken = readerModule.TablesStream.ReadMethodSemanticsRow(ridList[j], out semantics); var method = readerModule.ResolveMethod(methodToken); if (method == null) continue; Interlocked.CompareExchange(ref method.semAttrs, (int)semantics | MethodDef.SEMATTRS_INITD, 0); } } } /// /// Initializes a property's special methods /// /// The property /// Updated with a list of all get methods /// Updated with a list of all set methods /// Updated with a list of all other methods internal void InitializeProperty(PropertyDefMD prop, out ThreadSafe.IList getMethods, out ThreadSafe.IList setMethods, out ThreadSafe.IList otherMethods) { getMethods = ThreadSafeListCreator.Create(); setMethods = ThreadSafeListCreator.Create(); otherMethods = ThreadSafeListCreator.Create(); if (prop == null) return; var ridList = readerModule.MetaData.GetMethodSemanticsRidList(Table.Property, prop.OrigRid); for (uint i = 0; i < ridList.Length; i++) { MethodSemanticsAttributes semantics; uint methodToken = readerModule.TablesStream.ReadMethodSemanticsRow(ridList[i], out semantics); var method = readerModule.ResolveMethod(methodToken); if (method == null || method.DeclaringType != prop.DeclaringType) continue; // It's documented to be flags, but ignore those with more than one bit set switch (semantics) { case MethodSemanticsAttributes.Setter: if (!setMethods.Contains(method)) setMethods.Add(method); break; case MethodSemanticsAttributes.Getter: if (!getMethods.Contains(method)) getMethods.Add(method); break; case MethodSemanticsAttributes.Other: if (!otherMethods.Contains(method)) otherMethods.Add(method); break; default: // Ignore anything else break; } } } /// /// Initializes an event's special methods /// /// The event /// Updated with the addOn method or null if none /// Updated with the fire method or null if none /// Updated with the removeOn method or null if none /// Updated with a list of all other methods internal void InitializeEvent(EventDefMD evt, out MethodDef addMethod, out MethodDef invokeMethod, out MethodDef removeMethod, out ThreadSafe.IList otherMethods) { addMethod = null; invokeMethod = null; removeMethod = null; otherMethods = ThreadSafeListCreator.Create(); if (evt == null) return; var ridList = readerModule.MetaData.GetMethodSemanticsRidList(Table.Event, evt.OrigRid); for (uint i = 0; i < ridList.Length; i++) { MethodSemanticsAttributes semantics; uint methodToken = readerModule.TablesStream.ReadMethodSemanticsRow(ridList[i], out semantics); var method = readerModule.ResolveMethod(methodToken); if (method == null || method.DeclaringType != evt.DeclaringType) continue; // It's documented to be flags, but ignore those with more than one bit set switch (semantics) { case MethodSemanticsAttributes.AddOn: if (addMethod == null) addMethod = method; break; case MethodSemanticsAttributes.RemoveOn: if (removeMethod == null) removeMethod = method; break; case MethodSemanticsAttributes.Fire: if (invokeMethod == null) invokeMethod = method; break; case MethodSemanticsAttributes.Other: if (!otherMethods.Contains(method)) otherMethods.Add(method); break; default: // Ignore anything else break; } } } /// internal override void OnLazyAdd2(int index, ref FieldDef value) { if (value.DeclaringType != this) { // More than one owner... This module has invalid metadata. value = readerModule.ForceUpdateRowId(readerModule.ReadField(value.Rid).InitializeAll()); value.DeclaringType2 = this; } } /// internal override void OnLazyAdd2(int index, ref MethodDef value) { if (value.DeclaringType != this) { // More than one owner... This module has invalid metadata. value = readerModule.ForceUpdateRowId(readerModule.ReadMethod(value.Rid).InitializeAll()); value.DeclaringType2 = this; value.Parameters.UpdateThisParameterType(this); } } /// internal override void OnLazyAdd2(int index, ref EventDef value) { if (value.DeclaringType != this) { // More than one owner... This module has invalid metadata. value = readerModule.ForceUpdateRowId(readerModule.ReadEvent(value.Rid).InitializeAll()); value.DeclaringType2 = this; } } /// internal override void OnLazyAdd2(int index, ref PropertyDef value) { if (value.DeclaringType != this) { // More than one owner... This module has invalid metadata. value = readerModule.ForceUpdateRowId(readerModule.ReadProperty(value.Rid).InitializeAll()); value.DeclaringType2 = this; } } /// internal override void OnLazyAdd2(int index, ref GenericParam value) { if (value.Owner != this) { // More than one owner... This module has invalid metadata. value = readerModule.ForceUpdateRowId(readerModule.ReadGenericParam(value.Rid).InitializeAll()); value.Owner = this; } } } } dnlib-2.1_VS2010/src/DotNet/TypeDefFinder.cs000066400000000000000000000177171325033663500204050ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Text; using dnlib.Threading; namespace dnlib.DotNet { /// /// Finds s /// sealed class TypeDefFinder : ITypeDefFinder, IDisposable { const SigComparerOptions TypeComparerOptions = SigComparerOptions.DontCompareTypeScope | SigComparerOptions.TypeRefCanReferenceGlobalType; bool isCacheEnabled; readonly bool includeNestedTypes; Dictionary typeRefCache = new Dictionary(new TypeEqualityComparer(TypeComparerOptions)); Dictionary normalNameCache = new Dictionary(StringComparer.Ordinal); Dictionary reflectionNameCache = new Dictionary(StringComparer.Ordinal); readonly StringBuilder sb = new StringBuilder(); IEnumerator typeEnumerator; readonly IEnumerable rootTypes; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// /// true if the cache is enabled. false if the cache /// is disabled and a slower O(n) lookup is performed. /// public bool IsCacheEnabled { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return IsCacheEnabled_NoLock; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif IsCacheEnabled_NoLock = value; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } bool IsCacheEnabled_NoLock { get { return isCacheEnabled; } set { if (isCacheEnabled == value) return; if (typeEnumerator != null) { typeEnumerator.Dispose(); typeEnumerator = null; } typeRefCache.Clear(); normalNameCache.Clear(); reflectionNameCache.Clear(); if (value) InitializeTypeEnumerator(); isCacheEnabled = value; } } /// /// Constructor /// /// All root types. All their nested types are also included. /// If is null public TypeDefFinder(IEnumerable rootTypes) : this(rootTypes, true) { } /// /// Constructor /// /// All root types /// true if all nested types that are reachable /// from should also be included. /// If is null public TypeDefFinder(IEnumerable rootTypes, bool includeNestedTypes) { if (rootTypes == null) throw new ArgumentNullException("rootTypes"); this.rootTypes = rootTypes; this.includeNestedTypes = includeNestedTypes; } void InitializeTypeEnumerator() { if (typeEnumerator != null) { typeEnumerator.Dispose(); typeEnumerator = null; } typeEnumerator = (includeNestedTypes ? AllTypesHelper.Types(rootTypes) : rootTypes).GetEnumerator(); } /// /// Resets the cache (clears all cached elements). Use this method if the cache is /// enabled but some of the types have been modified (eg. removed, added, renamed). /// public void ResetCache() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif bool old = IsCacheEnabled_NoLock; IsCacheEnabled_NoLock = false; IsCacheEnabled_NoLock = old; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// public TypeDef Find(string fullName, bool isReflectionName) { if (fullName == null) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (isCacheEnabled) return isReflectionName ? FindCacheReflection(fullName) : FindCacheNormal(fullName); return isReflectionName ? FindSlowReflection(fullName) : FindSlowNormal(fullName); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// public TypeDef Find(TypeRef typeRef) { if (typeRef == null) return null; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif return isCacheEnabled ? FindCache(typeRef) : FindSlow(typeRef); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } TypeDef FindCache(TypeRef typeRef) { TypeDef cachedType; if (typeRefCache.TryGetValue(typeRef, out cachedType)) return cachedType; // Build the cache lazily var comparer = new SigComparer(TypeComparerOptions); while (true) { cachedType = GetNextTypeDefCache(); if (cachedType == null || comparer.Equals(cachedType, typeRef)) return cachedType; } } TypeDef FindCacheReflection(string fullName) { TypeDef cachedType; if (reflectionNameCache.TryGetValue(fullName, out cachedType)) return cachedType; // Build the cache lazily while (true) { cachedType = GetNextTypeDefCache(); if (cachedType == null) return cachedType; sb.Length = 0; if (FullNameCreator.FullName(cachedType, true, null, sb) == fullName) return cachedType; } } TypeDef FindCacheNormal(string fullName) { TypeDef cachedType; if (normalNameCache.TryGetValue(fullName, out cachedType)) return cachedType; // Build the cache lazily while (true) { cachedType = GetNextTypeDefCache(); if (cachedType == null) return cachedType; sb.Length = 0; if (FullNameCreator.FullName(cachedType, false, null, sb) == fullName) return cachedType; } } TypeDef FindSlow(TypeRef typeRef) { InitializeTypeEnumerator(); var comparer = new SigComparer(TypeComparerOptions); while (true) { var type = GetNextTypeDef(); if (type == null || comparer.Equals(type, typeRef)) return type; } } TypeDef FindSlowReflection(string fullName) { InitializeTypeEnumerator(); while (true) { var type = GetNextTypeDef(); if (type == null) return type; sb.Length = 0; if (FullNameCreator.FullName(type, true, null, sb) == fullName) return type; } } TypeDef FindSlowNormal(string fullName) { InitializeTypeEnumerator(); while (true) { var type = GetNextTypeDef(); if (type == null) return type; sb.Length = 0; if (FullNameCreator.FullName(type, false, null, sb) == fullName) return type; } } /// /// Gets the next or null if there are no more left /// /// The next or null if none TypeDef GetNextTypeDef() { while (typeEnumerator.MoveNext()) { var type = typeEnumerator.Current; if (type != null) return type; } return null; } /// /// Gets the next or null if there are no more left. /// The cache is updated with the returned before the method /// returns. /// /// The next or null if none TypeDef GetNextTypeDefCache() { var type = GetNextTypeDef(); if (type == null) return null; // Only insert it if another type with the exact same sig/name isn't already // in the cache. This should only happen with some obfuscated assemblies. if (!typeRefCache.ContainsKey(type)) typeRefCache[type] = type; string fn; sb.Length = 0; if (!normalNameCache.ContainsKey(fn = FullNameCreator.FullName(type, false, null, sb))) normalNameCache[fn] = type; sb.Length = 0; if (!reflectionNameCache.ContainsKey(fn = FullNameCreator.FullName(type, true, null, sb))) reflectionNameCache[fn] = type; return type; } /// public void Dispose() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (typeEnumerator != null) typeEnumerator.Dispose(); typeEnumerator = null; typeRefCache = null; normalNameCache = null; reflectionNameCache = null; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } } dnlib-2.1_VS2010/src/DotNet/TypeHelper.cs000066400000000000000000000277641325033663500200010ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// Various helper methods for classes to prevent infinite recursion /// struct TypeHelper { RecursionCounter recursionCounter; internal static bool ContainsGenericParameter(StandAloneSig ss) { return ss != null && TypeHelper.ContainsGenericParameter(ss.Signature); } internal static bool ContainsGenericParameter(InterfaceImpl ii) { return ii != null && TypeHelper.ContainsGenericParameter(ii.Interface); } internal static bool ContainsGenericParameter(GenericParamConstraint gpc) { return gpc != null && ContainsGenericParameter(gpc.Constraint); } internal static bool ContainsGenericParameter(MethodSpec ms) { if (ms == null) return false; // A normal MethodSpec should always contain generic arguments and thus // its MethodDef is always a generic method with generic parameters. return true; } internal static bool ContainsGenericParameter(MemberRef mr) { if (mr == null) return false; if (ContainsGenericParameter(mr.Signature)) return true; var cl = mr.Class; var tdr = cl as ITypeDefOrRef; if (tdr != null) return tdr.ContainsGenericParameter; var md = cl as MethodDef; if (md != null) return TypeHelper.ContainsGenericParameter(md.Signature); return false; } /// /// Checks whether contains a or a /// . /// /// Calling convention signature /// true if contains a /// or a . public static bool ContainsGenericParameter(CallingConventionSig callConv) { var fs = callConv as FieldSig; if (fs != null) return ContainsGenericParameter(fs); var mbs = callConv as MethodBaseSig; if (mbs != null) return ContainsGenericParameter(mbs); var ls = callConv as LocalSig; if (ls != null) return ContainsGenericParameter(ls); var gim = callConv as GenericInstMethodSig; if (gim != null) return ContainsGenericParameter(gim); return false; } /// /// Checks whether contains a or a /// . /// /// Field signature /// true if contains a /// or a . public static bool ContainsGenericParameter(FieldSig fieldSig) { return new TypeHelper().ContainsGenericParameterInternal(fieldSig); } /// /// Checks whether contains a or a /// . /// /// Method or property signature /// true if contains a /// or a . public static bool ContainsGenericParameter(MethodBaseSig methodSig) { return new TypeHelper().ContainsGenericParameterInternal(methodSig); } /// /// Checks whether contains a or a /// . /// /// Local signature /// true if contains a /// or a . public static bool ContainsGenericParameter(LocalSig localSig) { return new TypeHelper().ContainsGenericParameterInternal(localSig); } /// /// Checks whether contains a or a /// . /// /// Generic method signature /// true if contains a /// or a . public static bool ContainsGenericParameter(GenericInstMethodSig gim) { return new TypeHelper().ContainsGenericParameterInternal(gim); } /// /// Checks whether contains a or a /// . /// /// Type /// true if contains a or a /// . public static bool ContainsGenericParameter(IType type) { var td = type as TypeDef; if (td != null) return ContainsGenericParameter(td); var tr = type as TypeRef; if (tr != null) return ContainsGenericParameter(tr); var ts = type as TypeSpec; if (ts != null) return ContainsGenericParameter(ts); var sig = type as TypeSig; if (sig != null) return ContainsGenericParameter(sig); var et = type as ExportedType; if (et != null) return ContainsGenericParameter(et); return false; } /// /// Checks whether contains a or a /// . /// /// Type /// true if contains a or a /// . public static bool ContainsGenericParameter(TypeDef type) { return new TypeHelper().ContainsGenericParameterInternal(type); } /// /// Checks whether contains a or a /// . /// /// Type /// true if contains a or a /// . public static bool ContainsGenericParameter(TypeRef type) { return new TypeHelper().ContainsGenericParameterInternal(type); } /// /// Checks whether contains a or a /// . /// /// Type /// true if contains a or a /// . public static bool ContainsGenericParameter(TypeSpec type) { return new TypeHelper().ContainsGenericParameterInternal(type); } /// /// Checks whether contains a or a /// . /// /// Type /// true if contains a or a /// . public static bool ContainsGenericParameter(TypeSig type) { return new TypeHelper().ContainsGenericParameterInternal(type); } /// /// Checks whether contains a or a /// . /// /// Type /// true if contains a or a /// . public static bool ContainsGenericParameter(ExportedType type) { return new TypeHelper().ContainsGenericParameterInternal(type); } bool ContainsGenericParameterInternal(TypeDef type) { return false; } bool ContainsGenericParameterInternal(TypeRef type) { return false; } bool ContainsGenericParameterInternal(TypeSpec type) { if (type == null) return false; if (!recursionCounter.Increment()) return false; bool res = ContainsGenericParameterInternal(type.TypeSig); recursionCounter.Decrement(); return res; } bool ContainsGenericParameterInternal(ITypeDefOrRef tdr) { if (tdr == null) return false; // TypeDef and TypeRef contain no generic parameters return ContainsGenericParameterInternal(tdr as TypeSpec); } bool ContainsGenericParameterInternal(TypeSig type) { if (type == null) return false; if (!recursionCounter.Increment()) return false; bool res; switch (type.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.ValueType: case ElementType.Class: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: res = ContainsGenericParameterInternal((type as TypeDefOrRefSig).TypeDefOrRef); break; case ElementType.Var: case ElementType.MVar: res = true; break; case ElementType.FnPtr: res = ContainsGenericParameterInternal((type as FnPtrSig).Signature); break; case ElementType.GenericInst: var gi = (GenericInstSig)type; res = ContainsGenericParameterInternal(gi.GenericType) || ContainsGenericParameter(gi.GenericArguments); break; case ElementType.Ptr: case ElementType.ByRef: case ElementType.Array: case ElementType.SZArray: case ElementType.Pinned: case ElementType.ValueArray: case ElementType.Module: res = ContainsGenericParameterInternal((type as NonLeafSig).Next); break; case ElementType.CModReqd: case ElementType.CModOpt: res = ContainsGenericParameterInternal((type as ModifierSig).Modifier) || ContainsGenericParameterInternal((type as NonLeafSig).Next); break; case ElementType.End: case ElementType.R: case ElementType.Internal: case ElementType.Sentinel: default: res = false; break; } recursionCounter.Decrement(); return res; } bool ContainsGenericParameterInternal(ExportedType type) { return false; } bool ContainsGenericParameterInternal(CallingConventionSig callConv) { var fs = callConv as FieldSig; if (fs != null) return ContainsGenericParameterInternal(fs); var mbs = callConv as MethodBaseSig; if (mbs != null) return ContainsGenericParameterInternal(mbs); var ls = callConv as LocalSig; if (ls != null) return ContainsGenericParameterInternal(ls); var gim = callConv as GenericInstMethodSig; if (gim != null) return ContainsGenericParameterInternal(gim); return false; } bool ContainsGenericParameterInternal(FieldSig fs) { if (fs == null) return false; if (!recursionCounter.Increment()) return false; bool res = ContainsGenericParameterInternal(fs.Type); recursionCounter.Decrement(); return res; } bool ContainsGenericParameterInternal(MethodBaseSig mbs) { if (mbs == null) return false; if (!recursionCounter.Increment()) return false; bool res = ContainsGenericParameterInternal(mbs.RetType) || ContainsGenericParameter(mbs.Params) || ContainsGenericParameter(mbs.ParamsAfterSentinel); recursionCounter.Decrement(); return res; } bool ContainsGenericParameterInternal(LocalSig ls) { if (ls == null) return false; if (!recursionCounter.Increment()) return false; bool res = ContainsGenericParameter(ls.Locals); recursionCounter.Decrement(); return res; } bool ContainsGenericParameterInternal(GenericInstMethodSig gim) { if (gim == null) return false; if (!recursionCounter.Increment()) return false; bool res = ContainsGenericParameter(gim.GenericArguments); recursionCounter.Decrement(); return res; } bool ContainsGenericParameter(ThreadSafe.IList types) { if (types == null) return false; if (!recursionCounter.Increment()) return false; bool res = false; foreach (var type in types.GetSafeEnumerable()) { if (ContainsGenericParameter(type)) { res = true; break; } } recursionCounter.Decrement(); return res; } } } dnlib-2.1_VS2010/src/DotNet/TypeNameParser.cs000066400000000000000000000661761325033663500206170ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; using System.Text; namespace dnlib.DotNet { /// /// Thrown by when it fails to parse a type name /// [Serializable] public class TypeNameParserException : Exception { /// /// Default constructor /// public TypeNameParserException() { } /// /// Constructor /// /// Exception message public TypeNameParserException(string message) : base(message) { } /// /// Constructor /// /// Exception message /// Inner exception or null if none public TypeNameParserException(string message, Exception innerException) : base(message, innerException) { } /// /// Constructor /// /// /// protected TypeNameParserException(SerializationInfo info, StreamingContext context) : base(info, context) { } } /// /// Helps create types /// public interface IAssemblyRefFinder { /// /// Finds a 's when the original assembly /// info is missing from the full type name. /// /// A non-nested /// 's or null AssemblyRef FindAssemblyRef(TypeRef nonNestedTypeRef); } /// /// Parses a type name and creates an /// public abstract class TypeNameParser : IDisposable { /// Owner module protected ModuleDef ownerModule; readonly GenericParamContext gpContext; StringReader reader; readonly IAssemblyRefFinder typeNameParserHelper; RecursionCounter recursionCounter; /// /// Parses a Reflection type name and creates a /// /// Module that will own the returned or null /// Full name of type /// Helper class /// A new instance /// If parsing failed public static ITypeDefOrRef ParseReflectionThrow(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper) { return ParseReflectionThrow(ownerModule, typeFullName, typeNameParserHelper, new GenericParamContext()); } /// /// Parses a Reflection type name and creates a /// /// Module that will own the returned or null /// Full name of type /// Helper class /// Generic parameter context /// A new instance /// If parsing failed public static ITypeDefOrRef ParseReflectionThrow(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper, GenericParamContext gpContext) { using (var parser = new ReflectionTypeNameParser(ownerModule, typeFullName, typeNameParserHelper, gpContext)) return parser.Parse(); } /// /// Parses a Reflection type name and creates a /// /// Module that will own the returned or null /// Full name of type /// Helper class /// A new instance or null if parsing failed public static ITypeDefOrRef ParseReflection(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper) { return ParseReflection(ownerModule, typeFullName, typeNameParserHelper, new GenericParamContext()); } /// /// Parses a Reflection type name and creates a /// /// Module that will own the returned or null /// Full name of type /// Helper class /// Generic parameter context /// A new instance or null if parsing failed public static ITypeDefOrRef ParseReflection(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper, GenericParamContext gpContext) { try { return ParseReflectionThrow(ownerModule, typeFullName, typeNameParserHelper, gpContext); } catch (TypeNameParserException) { return null; } } /// /// Parses a Reflection type name and creates a /// /// Module that will own the returned or null /// Full name of type /// Helper class /// A new instance /// If parsing failed public static TypeSig ParseAsTypeSigReflectionThrow(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper) { return ParseAsTypeSigReflectionThrow(ownerModule, typeFullName, typeNameParserHelper, new GenericParamContext()); } /// /// Parses a Reflection type name and creates a /// /// Module that will own the returned or null /// Full name of type /// Helper class /// Generic parameter context /// A new instance /// If parsing failed public static TypeSig ParseAsTypeSigReflectionThrow(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper, GenericParamContext gpContext) { using (var parser = new ReflectionTypeNameParser(ownerModule, typeFullName, typeNameParserHelper, gpContext)) return parser.ParseAsTypeSig(); } /// /// Parses a Reflection type name and creates a /// /// Module that will own the returned or null /// Full name of type /// Helper class /// A new instance or null if parsing failed public static TypeSig ParseAsTypeSigReflection(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper) { return ParseAsTypeSigReflection(ownerModule, typeFullName, typeNameParserHelper, new GenericParamContext()); } /// /// Parses a Reflection type name and creates a /// /// Module that will own the returned or null /// Full name of type /// Helper class /// Generic parameter context /// A new instance or null if parsing failed public static TypeSig ParseAsTypeSigReflection(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper, GenericParamContext gpContext) { try { return ParseAsTypeSigReflectionThrow(ownerModule, typeFullName, typeNameParserHelper, gpContext); } catch (TypeNameParserException) { return null; } } /// /// Constructor /// /// Module that will own the returned or null /// Full name of type /// Helper class protected TypeNameParser(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper) : this(ownerModule, typeFullName, typeNameParserHelper, new GenericParamContext()) { } /// /// Constructor /// /// Module that will own the returned or null /// Full name of type /// Helper class /// Generic parameter context protected TypeNameParser(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper, GenericParamContext gpContext) { this.ownerModule = ownerModule; this.reader = new StringReader(typeFullName ?? string.Empty); this.typeNameParserHelper = typeNameParserHelper; this.gpContext = gpContext; } /// /// Parses a type name and creates a /// /// A new instance /// If parsing failed internal ITypeDefOrRef Parse() { return ownerModule.UpdateRowId(ParseAsTypeSig().ToTypeDefOrRef()); } /// /// Parses a type name and creates a /// /// A new instance /// If parsing failed internal abstract TypeSig ParseAsTypeSig(); /// /// Increment recursion counter /// /// If this method has been called too many times protected void RecursionIncrement() { if (!recursionCounter.Increment()) throw new TypeNameParserException("Stack overflow"); } /// /// Decrement recursion counter /// protected void RecursionDecrement() { recursionCounter.Decrement(); } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose method /// /// true if called by protected virtual void Dispose(bool disposing) { if (!disposing) return; if (reader != null) reader.Dispose(); reader = null; } internal abstract class TSpec { public readonly ElementType etype; protected TSpec(ElementType etype) { this.etype = etype; } } internal sealed class SZArraySpec : TSpec { public static readonly SZArraySpec Instance = new SZArraySpec(); SZArraySpec() : base(ElementType.SZArray) { } } internal sealed class ArraySpec : TSpec { public uint rank; public readonly IList sizes = new List(); public readonly IList lowerBounds = new List(); public ArraySpec() : base(ElementType.Array) { } } internal sealed class GenericInstSpec : TSpec { public readonly List args = new List(); public GenericInstSpec() : base(ElementType.GenericInst) { } } internal sealed class ByRefSpec : TSpec { public static readonly ByRefSpec Instance = new ByRefSpec(); ByRefSpec() : base(ElementType.ByRef) { } } internal sealed class PtrSpec : TSpec { public static readonly PtrSpec Instance = new PtrSpec(); PtrSpec() : base(ElementType.Ptr) { } } internal GenericSig ReadGenericSig() { Verify(ReadChar() == '!', "Expected '!'"); if (PeekChar() == '!') { ReadChar(); return new GenericMVar(ReadUInt32(), gpContext.Method); } return new GenericVar(ReadUInt32(), gpContext.Type); } internal TypeSig CreateTypeSig(IList tspecs, TypeSig currentSig) { foreach (var tspec in tspecs) { switch (tspec.etype) { case ElementType.SZArray: currentSig = new SZArraySig(currentSig); break; case ElementType.Array: var arraySpec = (ArraySpec)tspec; currentSig = new ArraySig(currentSig, arraySpec.rank, arraySpec.sizes, arraySpec.lowerBounds); break; case ElementType.GenericInst: var ginstSpec = (GenericInstSpec)tspec; currentSig = new GenericInstSig(currentSig as ClassOrValueTypeSig, ginstSpec.args); break; case ElementType.ByRef: currentSig = new ByRefSig(currentSig); break; case ElementType.Ptr: currentSig = new PtrSig(currentSig); break; default: Verify(false, "Unknown TSpec"); break; } } return currentSig; } /// /// Reads a including any possible nested s. /// /// Character separating nested types /// A new instance, which could be nested. protected TypeRef ReadTypeRefAndNestedNoAssembly(char nestedChar) { var typeRef = ReadTypeRefNoAssembly(); while (true) { SkipWhite(); if (PeekChar() != nestedChar) break; ReadChar(); var newTypeRef = ReadTypeRefNoAssembly(); newTypeRef.ResolutionScope = typeRef; typeRef = newTypeRef; } return typeRef; } /// /// Reads a namespace and name and creates a TypeRef. Does not read any nested types. /// /// A new instance protected TypeRef ReadTypeRefNoAssembly() { string ns, name; // White space is important here. Any white space before the comma/EOF must be // parsed as part of the name. GetNamespaceAndName(ReadId(false), out ns, out name); return ownerModule.UpdateRowId(new TypeRefUser(ownerModule, ns, name)); } static void GetNamespaceAndName(string fullName, out string ns, out string name) { int index = fullName.LastIndexOf('.'); if (index < 0) { ns = string.Empty; name = fullName; } else { ns = fullName.Substring(0, index); name = fullName.Substring(index + 1); } } internal TypeSig ToTypeSig(ITypeDefOrRef type) { var td = type as TypeDef; if (td != null) return ToTypeSig(td, td.IsValueType); var tr = type as TypeRef; if (tr != null) return ToTypeSig(tr, IsValueType(tr)); var ts = type as TypeSpec; if (ts != null) return ts.TypeSig; Verify(false, "Unknown type"); return null; } static TypeSig ToTypeSig(ITypeDefOrRef type, bool isValueType) { return isValueType ? (TypeSig)new ValueTypeSig(type) : new ClassSig(type); } internal AssemblyRef FindAssemblyRef(TypeRef nonNestedTypeRef) { AssemblyRef asmRef = null; if (nonNestedTypeRef != null && typeNameParserHelper != null) asmRef = typeNameParserHelper.FindAssemblyRef(nonNestedTypeRef); if (asmRef != null) return asmRef; var ownerAsm = ownerModule.Assembly; if (ownerAsm != null) return ownerModule.UpdateRowId(ownerAsm.ToAssemblyRef()); return AssemblyRef.CurrentAssembly; } internal bool IsValueType(TypeRef typeRef) { return typeRef != null && typeRef.IsValueType; } internal static void Verify(bool b, string msg) { if (!b) throw new TypeNameParserException(msg); } internal void SkipWhite() { while (true) { int next = PeekChar(); if (next == -1) break; if (!char.IsWhiteSpace((char)next)) break; ReadChar(); } } internal uint ReadUInt32() { SkipWhite(); bool readInt = false; uint val = 0; while (true) { int c = PeekChar(); if (c == -1 || !(c >= '0' && c <= '9')) break; ReadChar(); uint newVal = val * 10 + (uint)(c - '0'); Verify(newVal >= val, "Integer overflow"); val = newVal; readInt = true; } Verify(readInt, "Expected an integer"); return val; } internal int ReadInt32() { SkipWhite(); bool isSigned = false; if (PeekChar() == '-') { isSigned = true; ReadChar(); } uint val = ReadUInt32(); if (isSigned) { Verify(val <= (uint)int.MaxValue + 1, "Integer overflow"); return -(int)val; } else { Verify(val <= (uint)int.MaxValue, "Integer overflow"); return (int)val; } } internal string ReadId() { return ReadId(true); } internal string ReadId(bool ignoreWhiteSpace) { SkipWhite(); var sb = new StringBuilder(); int c; while ((c = GetIdChar(ignoreWhiteSpace)) != -1) sb.Append((char)c); Verify(sb.Length > 0, "Expected an id"); return sb.ToString(); } /// /// Peeks the next char. -1 if no more chars. /// protected int PeekChar() { return reader.Peek(); } /// /// Gets the next char or -1 if no more chars /// protected int ReadChar() { return reader.Read(); } /// /// Gets the next ID char or -1 if no more ID chars /// /// true if white space should be ignored internal abstract int GetIdChar(bool ignoreWhiteSpace); } /// /// Parses reflection type names. Grammar http://msdn.microsoft.com/en-us/library/yfsftwz6.aspx /// sealed class ReflectionTypeNameParser : TypeNameParser { /// /// Constructor /// /// Module that will own the returned or null /// Full name of type /// Helper class public ReflectionTypeNameParser(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper) : base(ownerModule, typeFullName, typeNameParserHelper, new GenericParamContext()) { } /// /// Constructor /// /// Module that will own the returned or null /// Full name of type /// Helper class /// Generic parameter context public ReflectionTypeNameParser(ModuleDef ownerModule, string typeFullName, IAssemblyRefFinder typeNameParserHelper, GenericParamContext gpContext) : base(ownerModule, typeFullName, typeNameParserHelper, gpContext) { } /// /// Parses an assembly name /// /// Full assembly name /// A new instance or null if parsing failed public static AssemblyRef ParseAssemblyRef(string asmFullName) { return ParseAssemblyRef(asmFullName, new GenericParamContext()); } /// /// Parses an assembly name /// /// Full assembly name /// Generic parameter context /// A new instance or null if parsing failed public static AssemblyRef ParseAssemblyRef(string asmFullName, GenericParamContext gpContext) { try { using (var parser = new ReflectionTypeNameParser(null, asmFullName, null, gpContext)) return parser.ReadAssemblyRef(); } catch { return null; } } /// internal override TypeSig ParseAsTypeSig() { try { var type = ReadType(true); SkipWhite(); Verify(PeekChar() == -1, "Extra input after type name"); return type; } catch (TypeNameParserException) { throw; } catch (Exception ex) { throw new TypeNameParserException("Could not parse type name", ex); } } TypeSig ReadType(bool readAssemblyReference) { RecursionIncrement(); TypeSig result; SkipWhite(); if (PeekChar() == '!') { var currentSig = ReadGenericSig(); var tspecs = ReadTSpecs(); ReadOptionalAssemblyRef(); result = CreateTypeSig(tspecs, currentSig); } else { TypeRef typeRef = ReadTypeRefAndNestedNoAssembly('+'); var tspecs = ReadTSpecs(); var nonNestedTypeRef = TypeRef.GetNonNestedTypeRef(typeRef); AssemblyRef asmRef; if (readAssemblyReference) asmRef = ReadOptionalAssemblyRef() ?? FindAssemblyRef(nonNestedTypeRef); else asmRef = FindAssemblyRef(nonNestedTypeRef); nonNestedTypeRef.ResolutionScope = asmRef; // Make sure the CorLib types are used whenever possible result = null; if (typeRef == nonNestedTypeRef) { var corLibSig = ownerModule.CorLibTypes.GetCorLibTypeSig(typeRef.Namespace, typeRef.Name, typeRef.DefinitionAssembly); if (corLibSig != null) result = corLibSig; } if (result == null) { var typeDef = Resolve(asmRef, typeRef); result = ToTypeSig(typeDef != null ? (ITypeDefOrRef)typeDef : typeRef); } if (tspecs.Count != 0) result = CreateTypeSig(tspecs, result); } RecursionDecrement(); return result; } TypeDef Resolve(AssemblyRef asmRef, TypeRef typeRef) { var asm = ownerModule.Assembly; if (asm == null) return null; if (!(AssemblyNameComparer.CompareAll.Equals(asmRef, asm) && asmRef.IsRetargetable == asm.IsRetargetable)) return null; var td = typeRef.Resolve(); return td != null && td.Module == ownerModule ? td : null; } AssemblyRef ReadOptionalAssemblyRef() { SkipWhite(); if (PeekChar() == ',') { ReadChar(); return ReadAssemblyRef(); } return null; } IList ReadTSpecs() { var tspecs = new List(); while (true) { SkipWhite(); switch (PeekChar()) { case '[': // SZArray, Array, or GenericInst ReadChar(); SkipWhite(); var peeked = PeekChar(); if (peeked == ']') { // SZ array Verify(ReadChar() == ']', "Expected ']'"); tspecs.Add(SZArraySpec.Instance); } else if (peeked == '*' || peeked == ',' || peeked == '-' || char.IsDigit((char)peeked)) { // Array var arraySpec = new ArraySpec(); arraySpec.rank = 0; while (true) { SkipWhite(); int c = PeekChar(); if (c == '*') ReadChar(); else if (c == ',' || c == ']') { } else if (c == '-' || char.IsDigit((char)c)) { int lower = ReadInt32(); uint? size; SkipWhite(); Verify(ReadChar() == '.', "Expected '.'"); Verify(ReadChar() == '.', "Expected '.'"); if (PeekChar() == '.') { ReadChar(); size = null; } else { SkipWhite(); if (PeekChar() == '-') { int upper = ReadInt32(); Verify(upper >= lower, "upper < lower"); size = (uint)(upper - lower + 1); Verify(size.Value != 0 && size.Value <= 0x1FFFFFFF, "Invalid size"); } else { uint upper = ReadUInt32(); long lsize = (long)upper - (long)lower + 1; Verify(lsize > 0 && lsize <= 0x1FFFFFFF, "Invalid size"); size = (uint)lsize; } } if (arraySpec.lowerBounds.Count == arraySpec.rank) arraySpec.lowerBounds.Add(lower); if (size.HasValue && arraySpec.sizes.Count == arraySpec.rank) arraySpec.sizes.Add(size.Value); } else Verify(false, "Unknown char"); arraySpec.rank++; SkipWhite(); if (PeekChar() != ',') break; ReadChar(); } Verify(ReadChar() == ']', "Expected ']'"); tspecs.Add(arraySpec); } else { // Generic args var ginstSpec = new GenericInstSpec(); while (true) { SkipWhite(); peeked = PeekChar(); bool needSeperators = peeked == '['; if (peeked == ']') break; Verify(!needSeperators || ReadChar() == '[', "Expected '['"); ginstSpec.args.Add(ReadType(needSeperators)); SkipWhite(); Verify(!needSeperators || ReadChar() == ']', "Expected ']'"); SkipWhite(); if (PeekChar() != ',') break; ReadChar(); } Verify(ReadChar() == ']', "Expected ']'"); tspecs.Add(ginstSpec); } break; case '&': // ByRef ReadChar(); tspecs.Add(ByRefSpec.Instance); break; case '*': // Ptr ReadChar(); tspecs.Add(PtrSpec.Instance); break; default: return tspecs; } } } AssemblyRef ReadAssemblyRef() { var asmRef = new AssemblyRefUser(); if (ownerModule != null) ownerModule.UpdateRowId(asmRef); asmRef.Name = ReadAssemblyNameId(); SkipWhite(); if (PeekChar() != ',') return asmRef; ReadChar(); while (true) { SkipWhite(); int c = PeekChar(); if (c == -1 || c == ']') break; if (c == ',') { ReadChar(); continue; } string key = ReadId(); SkipWhite(); if (PeekChar() != '=') continue; ReadChar(); string value = ReadId(); switch (key.ToUpperInvariant()) { case "VERSION": asmRef.Version = Utils.ParseVersion(value); break; case "CONTENTTYPE": if (value.Equals("WindowsRuntime", StringComparison.OrdinalIgnoreCase)) asmRef.ContentType = AssemblyAttributes.ContentType_WindowsRuntime; else asmRef.ContentType = AssemblyAttributes.ContentType_Default; break; case "RETARGETABLE": if (value.Equals("Yes", StringComparison.OrdinalIgnoreCase)) asmRef.IsRetargetable = true; else asmRef.IsRetargetable = false; break; case "PUBLICKEY": if (value.Equals("null", StringComparison.OrdinalIgnoreCase) || value.Equals("neutral", StringComparison.OrdinalIgnoreCase)) asmRef.PublicKeyOrToken = new PublicKey(); else asmRef.PublicKeyOrToken = PublicKeyBase.CreatePublicKey(Utils.ParseBytes(value)); break; case "PUBLICKEYTOKEN": if (value.Equals("null", StringComparison.OrdinalIgnoreCase) || value.Equals("neutral", StringComparison.OrdinalIgnoreCase)) asmRef.PublicKeyOrToken = new PublicKeyToken(); else asmRef.PublicKeyOrToken = PublicKeyBase.CreatePublicKeyToken(Utils.ParseBytes(value)); break; case "CULTURE": case "LANGUAGE": if (value.Equals("neutral", StringComparison.OrdinalIgnoreCase)) asmRef.Culture = UTF8String.Empty; else asmRef.Culture = value; break; } } return asmRef; } string ReadAssemblyNameId() { SkipWhite(); var sb = new StringBuilder(); int c; while ((c = GetAsmNameChar()) != -1) sb.Append((char)c); var name = sb.ToString().Trim(); Verify(name.Length > 0, "Expected an assembly name"); return name; } int GetAsmNameChar() { int c = PeekChar(); if (c == -1) return -1; switch (c) { case '\\': ReadChar(); return ReadChar(); case ']': case ',': return -1; default: return ReadChar(); } } internal override int GetIdChar(bool ignoreWhiteSpace) { int c = PeekChar(); if (c == -1) return -1; if (ignoreWhiteSpace && char.IsWhiteSpace((char)c)) return -1; switch (c) { case '\\': ReadChar(); return ReadChar(); case ',': case '+': case '&': case '*': case '[': case ']': case '=': return -1; default: return ReadChar(); } } } } dnlib-2.1_VS2010/src/DotNet/TypeRef.cs000066400000000000000000000314351325033663500172640ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the TypeRef table /// public abstract class TypeRef : ITypeDefOrRef, IHasCustomAttribute, IMemberRefParent, IHasCustomDebugInformation, IResolutionScope { /// /// The row id in its table /// protected uint rid; /// /// The owner module /// protected ModuleDef module; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// public MDToken MDToken { get { return new MDToken(Table.TypeRef, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int TypeDefOrRefTag { get { return 1; } } /// public int HasCustomAttributeTag { get { return 2; } } /// public int MemberRefParentTag { get { return 1; } } /// public int ResolutionScopeTag { get { return 3; } } /// int IGenericParameterProvider.NumberOfGenericParameters { get { return 0; } } /// string IType.TypeName { get { return FullNameCreator.Name(this, false, null); } } /// public string ReflectionName { get { return FullNameCreator.Name(this, true, null); } } /// string IType.Namespace { get { return FullNameCreator.Namespace(this, false, null); } } /// public string ReflectionNamespace { get { return FullNameCreator.Namespace(this, true, null); } } /// public string FullName { get { return FullNameCreator.FullName(this, false, null, null); } } /// public string ReflectionFullName { get { return FullNameCreator.FullName(this, true, null, null); } } /// public string AssemblyQualifiedName { get { return FullNameCreator.AssemblyQualifiedName(this, null, null); } } /// public IAssembly DefinitionAssembly { get { return FullNameCreator.DefinitionAssembly(this); } } /// public IScope Scope { get { return FullNameCreator.Scope(this); } } /// public ITypeDefOrRef ScopeType { get { return this; } } /// /// Always returns false since a does not contain any /// or . /// public bool ContainsGenericParameter { get { return false; } } /// public ModuleDef Module { get { return module; } } /// /// From column TypeRef.ResolutionScope /// public IResolutionScope ResolutionScope { get { if (!resolutionScope_isInitialized) InitializeResolutionScope(); return resolutionScope; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif resolutionScope = value; resolutionScope_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// protected IResolutionScope resolutionScope; /// protected bool resolutionScope_isInitialized; void InitializeResolutionScope() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (resolutionScope_isInitialized) return; resolutionScope = GetResolutionScope_NoLock(); resolutionScope_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual IResolutionScope GetResolutionScope_NoLock() { return null; } /// /// From column TypeRef.Name /// public UTF8String Name { get { return name; } set { name = value; } } /// Name protected UTF8String name; /// /// From column TypeRef.Namespace /// public UTF8String Namespace { get { return @namespace; } set { @namespace = value; } } /// Name protected UTF8String @namespace; /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 2; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// /// true if it's nested within another /// public bool IsNested { get { return DeclaringType != null; } } /// public bool IsValueType { get { var td = Resolve(); return td != null && td.IsValueType; } } /// public bool IsPrimitive { get { return this.IsPrimitive(); } } /// /// Gets the declaring type, if any /// public TypeRef DeclaringType { get { return ResolutionScope as TypeRef; } } /// ITypeDefOrRef IMemberRef.DeclaringType { get { return DeclaringType; } } bool IIsTypeOrMethod.IsType { get { return true; } } bool IIsTypeOrMethod.IsMethod { get { return false; } } bool IMemberRef.IsField { get { return false; } } bool IMemberRef.IsTypeSpec { get { return false; } } bool IMemberRef.IsTypeRef { get { return true; } } bool IMemberRef.IsTypeDef { get { return false; } } bool IMemberRef.IsMethodSpec { get { return false; } } bool IMemberRef.IsMethodDef { get { return false; } } bool IMemberRef.IsMemberRef { get { return false; } } bool IMemberRef.IsFieldDef { get { return false; } } bool IMemberRef.IsPropertyDef { get { return false; } } bool IMemberRef.IsEventDef { get { return false; } } bool IMemberRef.IsGenericParam { get { return false; } } /// /// Resolves the type /// /// A instance or null if it couldn't be resolved public TypeDef Resolve() { return Resolve(null); } /// /// Resolves the type /// /// The module that needs to resolve the type or null /// A instance or null if it couldn't be resolved public TypeDef Resolve(ModuleDef sourceModule) { if (module == null) return null; return module.Context.Resolver.Resolve(this, sourceModule ?? module); } /// /// Resolves the type /// /// A instance /// If the type couldn't be resolved public TypeDef ResolveThrow() { return ResolveThrow(null); } /// /// Resolves the type /// /// The module that needs to resolve the type or null /// A instance /// If the type couldn't be resolved public TypeDef ResolveThrow(ModuleDef sourceModule) { var type = Resolve(sourceModule); if (type != null) return type; throw new TypeResolveException(string.Format("Could not resolve type: {0} ({1})", this, DefinitionAssembly)); } /// /// Gets the top-most (non-nested) /// /// Input /// The non-nested or null internal static TypeRef GetNonNestedTypeRef(TypeRef typeRef) { if (typeRef == null) return null; for (int i = 0; i < 1000; i++) { var next = typeRef.ResolutionScope as TypeRef; if (next == null) return typeRef; typeRef = next; } return null; // Here if eg. the TypeRef has an infinite loop } /// public override string ToString() { return FullName; } } /// /// A TypeRef row created by the user and not present in the original .NET file /// public class TypeRefUser : TypeRef { /// /// Constructor /// /// Owner module /// Type name public TypeRefUser(ModuleDef module, UTF8String name) : this(module, UTF8String.Empty, name) { } /// /// Constructor /// /// Owner module /// Type namespace /// Type name public TypeRefUser(ModuleDef module, UTF8String @namespace, UTF8String name) : this(module, @namespace, name, null) { } /// /// Constructor /// /// Owner module /// Type namespace /// Type name /// Resolution scope (a , /// , or ) public TypeRefUser(ModuleDef module, UTF8String @namespace, UTF8String name, IResolutionScope resolutionScope) { this.module = module; this.resolutionScope = resolutionScope; this.resolutionScope_isInitialized = true; this.name = name; this.@namespace = @namespace; } } /// /// Created from a row in the TypeRef table /// sealed class TypeRefMD : TypeRef, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; readonly uint resolutionScopeCodedToken; /// public uint OrigRid { get { return origRid; } } /// protected override IResolutionScope GetResolutionScope_NoLock() { return readerModule.ResolveResolutionScope(resolutionScopeCodedToken); } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.TypeRef, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), new GenericParamContext(), list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this TypeRef row /// Row ID /// If is null /// If is invalid public TypeRefMD(ModuleDefMD readerModule, uint rid) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.TypeRefTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("TypeRef rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; this.module = readerModule; uint resolutionScope, name; uint @namespace = readerModule.TablesStream.ReadTypeRefRow(origRid, out resolutionScope, out name); this.name = readerModule.StringsStream.ReadNoNull(name); this.@namespace = readerModule.StringsStream.ReadNoNull(@namespace); this.resolutionScopeCodedToken = resolutionScope; } } } dnlib-2.1_VS2010/src/DotNet/TypeSig.cs000066400000000000000000001207651325033663500172770ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using dnlib.DotNet.MD; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif /* All TypeSig classes: TypeSig base class LeafSig base class for leaf types TypeDefOrRefSig contains a ITypeDefOrRef instance CorLibTypeSig simple corlib types (eg. System.Int32) ClassOrValueTypeSig base class for Class/ValueType element types ValueTypeSig ValueType ClassSig Class GenericSig base class for generic vars GenericVar Generic type parameter GenericMVar Generic method parameter SentinelSig Sentinel FnPtrSig Function pointer sig GenericInstSig Generic instance type (contains a generic type + all generic args) NonLeafSig base class for non-leaf types PtrSig Pointer ByRefSig By ref ArraySigBase Array base class ArraySig Array SZArraySig Single dimension, zero lower limit array (i.e., THETYPE[]) ModifierSig C modifier base class CModReqdSig C required modifier CModOptSig C optional modifier PinnedSig Pinned ValueArraySig Value array (undocumented/not implemented by the CLR so don't use it) ModuleSig Module (undocumented/not implemented by the CLR so don't use it) */ namespace dnlib.DotNet { /// /// Type sig base class /// public abstract class TypeSig : IType { uint rid; /// /// Returns the wrapped element type. Can only be null if it was an invalid sig or /// if it's a /// public abstract TypeSig Next { get; } /// /// Gets the element type /// public abstract ElementType ElementType { get; } /// public MDToken MDToken { get { return new MDToken(Table.TypeSpec, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// bool IIsTypeOrMethod.IsMethod { get { return false; } } /// bool IIsTypeOrMethod.IsType { get { return true; } } /// int IGenericParameterProvider.NumberOfGenericParameters { get { var type = this.RemovePinnedAndModifiers() as GenericInstSig; return type == null ? 0 : type.GenericArguments.Count; } } /// public bool IsValueType { get { var t = this.RemovePinnedAndModifiers(); if (t == null) return false; if (t.ElementType == ElementType.GenericInst) { var gis = (GenericInstSig)t; t = gis.GenericType; if (t == null) return false; } return t.ElementType.IsValueType(); } } /// public bool IsPrimitive { get { return ElementType.IsPrimitive(); } } /// public string TypeName { get { return FullNameCreator.Name(this, false, null); } } /// UTF8String IFullName.Name { get { return new UTF8String(FullNameCreator.Name(this, false, null)); } set { throw new NotSupportedException(); } } /// public string ReflectionName { get { return FullNameCreator.Name(this, true, null); } } /// public string Namespace { get { return FullNameCreator.Namespace(this, false, null); } } /// public string ReflectionNamespace { get { return FullNameCreator.Namespace(this, true, null); } } /// public string FullName { get { return FullNameCreator.FullName(this, false, null, null, null, null); } } /// public string ReflectionFullName { get { return FullNameCreator.FullName(this, true, null, null, null, null); } } /// public string AssemblyQualifiedName { get { return FullNameCreator.AssemblyQualifiedName(this, null, null); } } /// public IAssembly DefinitionAssembly { get { return FullNameCreator.DefinitionAssembly(this); } } /// public IScope Scope { get { return FullNameCreator.Scope(this); } } /// public ITypeDefOrRef ScopeType { get { return FullNameCreator.ScopeType(this); } } /// public ModuleDef Module { get { return FullNameCreator.OwnerModule(this); } } /// /// true if it's a /// public bool IsTypeDefOrRef { get { return this is TypeDefOrRefSig; } } /// /// true if it's a /// public bool IsCorLibType { get { return this is CorLibTypeSig; } } /// /// true if it's a /// public bool IsClassSig { get { return this is ClassSig; } } /// /// true if it's a /// public bool IsValueTypeSig { get { return this is ValueTypeSig; } } /// /// true if it's a /// public bool IsGenericParameter { get { return this is GenericSig; } } /// /// true if it's a /// public bool IsGenericTypeParameter { get { return this is GenericVar; } } /// /// true if it's a /// public bool IsGenericMethodParameter { get { return this is GenericMVar; } } /// /// true if it's a /// public bool IsSentinel { get { return this is SentinelSig; } } /// /// true if it's a /// public bool IsFunctionPointer { get { return this is FnPtrSig; } } /// /// true if it's a /// public bool IsGenericInstanceType { get { return this is GenericInstSig; } } /// /// true if it's a /// public bool IsPointer { get { return this is PtrSig; } } /// /// true if it's a /// public bool IsByRef { get { return this is ByRefSig; } } /// /// true if it's a or a /// public bool IsSingleOrMultiDimensionalArray { get { return this is ArraySigBase; } } /// /// true if it's a /// public bool IsArray { get { return this is ArraySig; } } /// /// true if it's a /// public bool IsSZArray { get { return this is SZArraySig; } } /// /// true if it's a /// public bool IsModifier { get { return this is ModifierSig; } } /// /// true if it's a /// public bool IsRequiredModifier { get { return this is CModReqdSig; } } /// /// true if it's a /// public bool IsOptionalModifier { get { return this is CModOptSig; } } /// /// true if it's a /// public bool IsPinned { get { return this is PinnedSig; } } /// /// true if it's a /// public bool IsValueArray { get { return this is ValueArraySig; } } /// /// true if it's a /// public bool IsModuleSig { get { return this is ModuleSig; } } /// /// true if this contains a or a /// . /// public bool ContainsGenericParameter { get { return TypeHelper.ContainsGenericParameter(this); } } /// public override string ToString() { return FullName; } } public static partial class Extensions { /// /// Removes all C optional/required modifiers /// /// A instance /// Input after all modifiers public static TypeSig RemoveModifiers(this TypeSig a) { if (a == null) return null; while (true) { var modifier = a as ModifierSig; if (modifier == null) return a; a = a.Next; } } /// /// Removes pinned signature /// /// The type /// Input after pinned signature public static TypeSig RemovePinned(this TypeSig a) { var pinned = a as PinnedSig; if (pinned == null) return a; return pinned.Next; } /// /// Removes all modifiers and pinned sig /// /// The type /// Inputer after modifiers and pinned signature public static TypeSig RemovePinnedAndModifiers(this TypeSig a) { a = a.RemoveModifiers(); a = a.RemovePinned(); a = a.RemoveModifiers(); return a; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static TypeDefOrRefSig ToTypeDefOrRefSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as TypeDefOrRefSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static ClassOrValueTypeSig ToClassOrValueTypeSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as ClassOrValueTypeSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static ValueTypeSig ToValueTypeSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as ValueTypeSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static ClassSig ToClassSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as ClassSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static GenericSig ToGenericSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as GenericSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static GenericVar ToGenericVar(this TypeSig type) { return type.RemovePinnedAndModifiers() as GenericVar; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static GenericMVar ToGenericMVar(this TypeSig type) { return type.RemovePinnedAndModifiers() as GenericMVar; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static GenericInstSig ToGenericInstSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as GenericInstSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static PtrSig ToPtrSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as PtrSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static ByRefSig ToByRefSig(this TypeSig type) { return type.RemovePinnedAndModifiers() as ByRefSig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static ArraySig ToArraySig(this TypeSig type) { return type.RemovePinnedAndModifiers() as ArraySig; } /// /// Returns a /// /// The type /// A or null if it's not a /// public static SZArraySig ToSZArraySig(this TypeSig type) { return type.RemovePinnedAndModifiers() as SZArraySig; } /// /// Gets the next field or null /// /// this /// public static TypeSig GetNext(this TypeSig self) { return self == null ? null : self.Next; } /// /// Gets the value or false if /// is null /// /// this /// public static bool GetIsValueType(this TypeSig self) { return self == null ? false : self.IsValueType; } /// /// Gets the value or false if /// is null /// /// this /// public static bool GetIsPrimitive(this TypeSig self) { return self == null ? false : self.IsPrimitive; } /// /// Gets the element type /// /// this /// The element type public static ElementType GetElementType(this TypeSig a) { return a == null ? ElementType.End : a.ElementType; } /// /// Gets the full name of the type /// /// this /// Full name of the type public static string GetFullName(this TypeSig a) { return a == null ? string.Empty : a.FullName; } /// /// Gets the name of the type /// /// this /// Name of the type public static string GetName(this TypeSig a) { return a == null ? string.Empty : a.TypeName; } /// /// Gets the namespace of the type /// /// this /// Namespace of the type public static string GetNamespace(this TypeSig a) { return a == null ? string.Empty : a.Namespace; } /// /// Returns the if it is a . /// /// this /// A or null if none found public static TypeRef TryGetTypeRef(this TypeSig a) { var tdr = a.RemovePinnedAndModifiers() as TypeDefOrRefSig; return tdr == null ? null : tdr.TypeRef; } /// /// Returns the if it is a . /// Nothing is resolved. /// /// this /// A or null if none found public static TypeDef TryGetTypeDef(this TypeSig a) { var tdr = a.RemovePinnedAndModifiers() as TypeDefOrRefSig; return tdr == null ? null : tdr.TypeDef; } /// /// Returns the if it is a . /// /// this /// A or null if none found public static TypeSpec TryGetTypeSpec(this TypeSig a) { var tdr = a.RemovePinnedAndModifiers() as TypeDefOrRefSig; return tdr == null ? null : tdr.TypeSpec; } } /// /// Base class for element types that are last in a type sig, ie., /// , , , /// , /// public abstract class LeafSig : TypeSig { /// public sealed override TypeSig Next { get { return null; } } } /// /// Wraps a /// public abstract class TypeDefOrRefSig : LeafSig { readonly ITypeDefOrRef typeDefOrRef; /// /// Gets the the TypeDefOrRef /// public ITypeDefOrRef TypeDefOrRef { get { return typeDefOrRef; } } /// /// Returns true if != null /// public bool IsTypeRef { get { return TypeRef != null; } } /// /// Returns true if != null /// public bool IsTypeDef { get { return TypeDef != null; } } /// /// Returns true if != null /// public bool IsTypeSpec { get { return TypeSpec != null; } } /// /// Gets the or null if it's not a /// public TypeRef TypeRef { get { return typeDefOrRef as TypeRef; } } /// /// Gets the or null if it's not a /// public TypeDef TypeDef { get { return typeDefOrRef as TypeDef; } } /// /// Gets the or null if it's not a /// public TypeSpec TypeSpec { get { return typeDefOrRef as TypeSpec; } } /// /// Constructor /// /// A , or /// a protected TypeDefOrRefSig(ITypeDefOrRef typeDefOrRef) { this.typeDefOrRef = typeDefOrRef; } } /// /// A core library type /// public sealed class CorLibTypeSig : TypeDefOrRefSig { readonly ElementType elementType; /// /// Gets the element type /// public override ElementType ElementType { get { return elementType; } } /// /// Constructor /// /// The type which must be a or a /// . and null are not allowed. /// The type's element type public CorLibTypeSig(ITypeDefOrRef corType, ElementType elementType) : base(corType) { if (!(corType is TypeRef) && !(corType is TypeDef)) throw new ArgumentException("corType must be a TypeDef or a TypeRef. null and TypeSpec are invalid inputs."); this.elementType = elementType; } } /// /// Base class for class/valuetype element types /// public abstract class ClassOrValueTypeSig : TypeDefOrRefSig { /// /// Constructor /// /// A protected ClassOrValueTypeSig(ITypeDefOrRef typeDefOrRef) : base(typeDefOrRef) { } } /// /// Represents a /// public sealed class ValueTypeSig : ClassOrValueTypeSig { /// public override ElementType ElementType { get { return ElementType.ValueType; } } /// /// Constructor /// /// A public ValueTypeSig(ITypeDefOrRef typeDefOrRef) : base(typeDefOrRef) { } } /// /// Represents a /// public sealed class ClassSig : ClassOrValueTypeSig { /// public override ElementType ElementType { get { return ElementType.Class; } } /// /// Constructor /// /// A public ClassSig(ITypeDefOrRef typeDefOrRef) : base(typeDefOrRef) { } } /// /// Generic method/type var base class /// public abstract class GenericSig : LeafSig { readonly bool isTypeVar; readonly uint number; readonly ITypeOrMethodDef genericParamProvider; /// /// true if it has an owner or /// public bool HasOwner { get { return genericParamProvider != null; } } /// /// true if it has an owner ( is /// not null) /// public bool HasOwnerType { get { return OwnerType != null; } } /// /// true if it has an owner ( is /// not null) /// public bool HasOwnerMethod { get { return OwnerMethod != null; } } /// /// Gets the owner type or null if the owner is a or if it /// has no owner. /// public TypeDef OwnerType { get { return genericParamProvider as TypeDef; } } /// /// Gets the owner method or null if the owner is a or if it /// has no owner. /// public MethodDef OwnerMethod { get { return genericParamProvider as MethodDef; } } /// /// Gets the generic param number /// public uint Number { get { return number; } } /// /// Gets the corresponding or null if none exists. /// public GenericParam GenericParam { get { var gpp = genericParamProvider; if (gpp == null) return null; foreach (var gp in gpp.GenericParameters.GetSafeEnumerable()) { if (gp.Number == number) return gp; } return null; } } /// /// Constructor /// /// true if it's a Var, false if it's a MVar /// Generic param number protected GenericSig(bool isTypeVar, uint number) : this(isTypeVar, number, null) { } /// /// Constructor /// /// true if it's a Var, false if it's a MVar /// Generic param number /// Owner method/type or null protected GenericSig(bool isTypeVar, uint number, ITypeOrMethodDef genericParamProvider) { this.isTypeVar = isTypeVar; this.number = number; this.genericParamProvider = genericParamProvider; } /// /// Returns true if it's a MVar element type /// public bool IsMethodVar { get { return !isTypeVar; } } /// /// Returns true if it's a Var element type /// public bool IsTypeVar { get { return isTypeVar; } } } /// /// Represents a /// public sealed class GenericVar : GenericSig { /// public override ElementType ElementType { get { return ElementType.Var; } } /// public GenericVar(uint number) : base(true, number) { } /// public GenericVar(int number) : base(true, (uint)number) { } /// /// Constructor /// /// Generic parameter number /// Owner type or null public GenericVar(uint number, TypeDef genericParamProvider) : base(true, number, genericParamProvider) { } /// /// Constructor /// /// Generic parameter number /// Owner type or null public GenericVar(int number, TypeDef genericParamProvider) : base(true, (uint)number, genericParamProvider) { } } /// /// Represents a /// public sealed class GenericMVar : GenericSig { /// public override ElementType ElementType { get { return ElementType.MVar; } } /// public GenericMVar(uint number) : base(false, number) { } /// public GenericMVar(int number) : base(false, (uint)number) { } /// /// Constructor /// /// Generic parameter number /// Owner method or null public GenericMVar(uint number, MethodDef genericParamProvider) : base(false, number, genericParamProvider) { } /// /// Constructor /// /// Generic parameter number /// Owner method or null public GenericMVar(int number, MethodDef genericParamProvider) : base(false, (uint)number, genericParamProvider) { } } /// /// Represents a /// public sealed class SentinelSig : LeafSig { /// public override ElementType ElementType { get { return ElementType.Sentinel; } } } /// /// Represents a /// public sealed class FnPtrSig : LeafSig { readonly CallingConventionSig signature; /// public override ElementType ElementType { get { return ElementType.FnPtr; } } /// /// Gets the signature /// public CallingConventionSig Signature { get { return signature; } } /// /// Gets the /// public MethodSig MethodSig { get { return signature as MethodSig; } } /// /// Constructor /// /// The method signature public FnPtrSig(CallingConventionSig signature) { this.signature = signature; } } /// /// Represents a /// public sealed class GenericInstSig : LeafSig { ClassOrValueTypeSig genericType; readonly ThreadSafe.IList genericArgs; /// public override ElementType ElementType { get { return ElementType.GenericInst; } } /// /// Gets the generic type /// public ClassOrValueTypeSig GenericType { get { return genericType; } set { genericType = value; } } /// /// Gets the generic arguments (it's never null) /// public ThreadSafe.IList GenericArguments { get { return genericArgs; } } /// /// Default constructor /// public GenericInstSig() { this.genericArgs = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// The generic type public GenericInstSig(ClassOrValueTypeSig genericType) { this.genericType = genericType; this.genericArgs = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// The generic type /// Number of generic arguments public GenericInstSig(ClassOrValueTypeSig genericType, uint genArgCount) { this.genericType = genericType; this.genericArgs = ThreadSafeListCreator.Create((int)genArgCount); } /// /// Constructor /// /// The generic type /// Number of generic arguments public GenericInstSig(ClassOrValueTypeSig genericType, int genArgCount) : this(genericType, (uint)genArgCount) { } /// /// Constructor /// /// The generic type /// Generic argument #1 public GenericInstSig(ClassOrValueTypeSig genericType, TypeSig genArg1) { this.genericType = genericType; this.genericArgs = ThreadSafeListCreator.Create(genArg1); } /// /// Constructor /// /// The generic type /// Generic argument #1 /// Generic argument #2 public GenericInstSig(ClassOrValueTypeSig genericType, TypeSig genArg1, TypeSig genArg2) { this.genericType = genericType; this.genericArgs = ThreadSafeListCreator.Create(genArg1, genArg2); } /// /// Constructor /// /// The generic type /// Generic argument #1 /// Generic argument #2 /// Generic argument #3 public GenericInstSig(ClassOrValueTypeSig genericType, TypeSig genArg1, TypeSig genArg2, TypeSig genArg3) { this.genericType = genericType; this.genericArgs = ThreadSafeListCreator.Create(genArg1, genArg2, genArg3); } /// /// Constructor /// /// The generic type /// Generic arguments public GenericInstSig(ClassOrValueTypeSig genericType, params TypeSig[] genArgs) { this.genericType = genericType; this.genericArgs = ThreadSafeListCreator.Create(genArgs); } /// /// Constructor /// /// The generic type /// Generic arguments public GenericInstSig(ClassOrValueTypeSig genericType, IList genArgs) { this.genericType = genericType; this.genericArgs = ThreadSafeListCreator.Create(genArgs); } } /// /// Base class of non-leaf element types /// public abstract class NonLeafSig : TypeSig { readonly TypeSig nextSig; /// public sealed override TypeSig Next { get { return nextSig; } } /// /// Constructor /// /// Next sig protected NonLeafSig(TypeSig nextSig) { this.nextSig = nextSig; } } /// /// Represents a /// public sealed class PtrSig : NonLeafSig { /// public override ElementType ElementType { get { return ElementType.Ptr; } } /// /// Constructor /// /// The next element type public PtrSig(TypeSig nextSig) : base(nextSig) { } } /// /// Represents a /// public sealed class ByRefSig : NonLeafSig { /// public override ElementType ElementType { get { return ElementType.ByRef; } } /// /// Constructor /// /// The next element type public ByRefSig(TypeSig nextSig) : base(nextSig) { } } /// /// Array base class /// public abstract class ArraySigBase : NonLeafSig { /// /// Constructor /// /// Array type protected ArraySigBase(TypeSig arrayType) : base(arrayType) { } /// /// true if it's a multi-dimensional array (i.e., ), /// and false if it's a single-dimensional array (i.e., ) /// /// public bool IsMultiDimensional { get { return ElementType == ElementType.Array; } } /// /// true if it's a single-dimensional array (i.e., ), /// and false if it's a multi-dimensional array (i.e., ) /// /// public bool IsSingleDimensional { get { return ElementType == ElementType.SZArray; } } /// /// Gets/sets the rank (number of dimensions). This can only be set if /// is true /// public abstract uint Rank { get; set; } /// /// Gets all sizes. If it's a , then it will be an empty temporary /// list that is re-created every time this method is called. /// /// A list of sizes public abstract ThreadSafe.IList GetSizes(); /// /// Gets all lower bounds. If it's a , then it will be an empty /// temporary list that is re-created every time this method is called. /// /// A list of lower bounds public abstract ThreadSafe.IList GetLowerBounds(); } /// /// Represents a /// /// public sealed class ArraySig : ArraySigBase { uint rank; readonly ThreadSafe.IList sizes; readonly ThreadSafe.IList lowerBounds; /// public override ElementType ElementType { get { return ElementType.Array; } } /// /// Gets/sets the rank (max value is 0x1FFFFFFF) /// public override uint Rank { get { return rank; } set { rank = value; } } /// /// Gets all sizes (max elements is 0x1FFFFFFF) /// public ThreadSafe.IList Sizes { get { return sizes; } } /// /// Gets all lower bounds (max elements is 0x1FFFFFFF) /// public ThreadSafe.IList LowerBounds { get { return lowerBounds; } } /// /// Constructor /// /// Array type public ArraySig(TypeSig arrayType) : base(arrayType) { this.sizes = ThreadSafeListCreator.Create(); this.lowerBounds = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Array type /// Array rank public ArraySig(TypeSig arrayType, uint rank) : base(arrayType) { this.rank = rank; this.sizes = ThreadSafeListCreator.Create(); this.lowerBounds = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Array type /// Array rank public ArraySig(TypeSig arrayType, int rank) : this(arrayType, (uint)rank) { } /// /// Constructor /// /// Array type /// Array rank /// Sizes list. This instance will be the owner of this list. /// Lower bounds list. This instance will be the owner of this list. public ArraySig(TypeSig arrayType, uint rank, IEnumerable sizes, IEnumerable lowerBounds) : base(arrayType) { this.rank = rank; this.sizes = ThreadSafeListCreator.Create(sizes); this.lowerBounds = ThreadSafeListCreator.Create(lowerBounds); } /// /// Constructor /// /// Array type /// Array rank /// Sizes list. This instance will be the owner of this list. /// Lower bounds list. This instance will be the owner of this list. public ArraySig(TypeSig arrayType, int rank, IEnumerable sizes, IEnumerable lowerBounds) : this(arrayType, (uint)rank, sizes, lowerBounds) { } /// /// Constructor /// /// Array type /// Array rank /// Sizes list. This instance will be the owner of this list. /// Lower bounds list. This instance will be the owner of this list. internal ArraySig(TypeSig arrayType, uint rank, IList sizes, IList lowerBounds) : base(arrayType) { this.rank = rank; this.sizes = ThreadSafeListCreator.MakeThreadSafe(sizes); this.lowerBounds = ThreadSafeListCreator.MakeThreadSafe(lowerBounds); } /// public override ThreadSafe.IList GetSizes() { return sizes; } /// public override ThreadSafe.IList GetLowerBounds() { return lowerBounds; } } /// /// Represents a (single dimension, zero lower bound array) /// /// public sealed class SZArraySig : ArraySigBase { /// public override ElementType ElementType { get { return ElementType.SZArray; } } /// public override uint Rank { get { return 1; } set { throw new NotSupportedException(); } } /// /// Constructor /// /// The next element type public SZArraySig(TypeSig nextSig) : base(nextSig) { } /// public override ThreadSafe.IList GetSizes() { return ThreadSafeListCreator.Create(); } /// public override ThreadSafe.IList GetLowerBounds() { return ThreadSafeListCreator.Create(); } } /// /// Base class for modifier type sigs /// public abstract class ModifierSig : NonLeafSig { readonly ITypeDefOrRef modifier; /// /// Returns the modifier type /// public ITypeDefOrRef Modifier { get { return modifier; } } /// /// Constructor /// /// Modifier type /// The next element type protected ModifierSig(ITypeDefOrRef modifier, TypeSig nextSig) : base(nextSig) { this.modifier = modifier; } } /// /// Represents a /// public sealed class CModReqdSig : ModifierSig { /// public override ElementType ElementType { get { return ElementType.CModReqd; } } /// public CModReqdSig(ITypeDefOrRef modifier, TypeSig nextSig) : base(modifier, nextSig) { } } /// /// Represents a /// public sealed class CModOptSig : ModifierSig { /// public override ElementType ElementType { get { return ElementType.CModOpt; } } /// public CModOptSig(ITypeDefOrRef modifier, TypeSig nextSig) : base(modifier, nextSig) { } } /// /// Represents a /// public sealed class PinnedSig : NonLeafSig { /// public override ElementType ElementType { get { return ElementType.Pinned; } } /// /// Constructor /// /// The next element type public PinnedSig(TypeSig nextSig) : base(nextSig) { } } /// /// Represents a /// public sealed class ValueArraySig : NonLeafSig { uint size; /// public override ElementType ElementType { get { return ElementType.ValueArray; } } /// /// Gets/sets the size /// public uint Size { get { return size; } set { size = value; } } /// /// Constructor /// /// The next element type /// Size of the array public ValueArraySig(TypeSig nextSig, uint size) : base(nextSig) { this.size = size; } } /// /// Represents a /// public sealed class ModuleSig : NonLeafSig { uint index; /// public override ElementType ElementType { get { return ElementType.Module; } } /// /// Gets/sets the index /// public uint Index { get { return index; } set { index = value; } } /// /// Constructor /// /// Index /// The next element type public ModuleSig(uint index, TypeSig nextSig) : base(nextSig) { this.index = index; } } } dnlib-2.1_VS2010/src/DotNet/TypeSpec.cs000066400000000000000000000242631325033663500174430ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Threading; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// A high-level representation of a row in the TypeSpec table /// public abstract class TypeSpec : ITypeDefOrRef, IHasCustomAttribute, IMemberRefParent, IHasCustomDebugInformation { /// /// The row id in its table /// protected uint rid; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif /// public MDToken MDToken { get { return new MDToken(Table.TypeSpec, rid); } } /// public uint Rid { get { return rid; } set { rid = value; } } /// public int TypeDefOrRefTag { get { return 2; } } /// public int HasCustomAttributeTag { get { return 13; } } /// public int MemberRefParentTag { get { return 4; } } /// int IGenericParameterProvider.NumberOfGenericParameters { get { var ts = TypeSig; return ts == null ? 0 : ((IGenericParameterProvider)ts).NumberOfGenericParameters; } } /// UTF8String IFullName.Name { get { var mr = ScopeType; return mr == null ? UTF8String.Empty : mr.Name; } set { var mr = ScopeType; if (mr != null) mr.Name = value; } } /// ITypeDefOrRef IMemberRef.DeclaringType { get { var sig = TypeSig.RemovePinnedAndModifiers(); var gis = sig as GenericInstSig; if (gis != null) sig = gis.GenericType; var tdr = sig as TypeDefOrRefSig; if (tdr != null) { if (tdr.IsTypeDef || tdr.IsTypeRef) return tdr.TypeDefOrRef.DeclaringType; return null; // If it's another TypeSpec, just stop. Don't want possible inf recursion. } return null; } } bool IIsTypeOrMethod.IsType { get { return true; } } bool IIsTypeOrMethod.IsMethod { get { return false; } } bool IMemberRef.IsField { get { return false; } } bool IMemberRef.IsTypeSpec { get { return true; } } bool IMemberRef.IsTypeRef { get { return false; } } bool IMemberRef.IsTypeDef { get { return false; } } bool IMemberRef.IsMethodSpec { get { return false; } } bool IMemberRef.IsMethodDef { get { return false; } } bool IMemberRef.IsMemberRef { get { return false; } } bool IMemberRef.IsFieldDef { get { return false; } } bool IMemberRef.IsPropertyDef { get { return false; } } bool IMemberRef.IsEventDef { get { return false; } } bool IMemberRef.IsGenericParam { get { return false; } } /// public bool IsValueType { get { var sig = TypeSig; return sig != null && sig.IsValueType; } } /// public bool IsPrimitive { get { var sig = TypeSig; return sig != null && sig.IsPrimitive; } } /// public string TypeName { get { return FullNameCreator.Name(this, false, null); } } /// public string ReflectionName { get { return FullNameCreator.Name(this, true, null); } } /// string IType.Namespace { get { return FullNameCreator.Namespace(this, false, null); } } /// public string ReflectionNamespace { get { return FullNameCreator.Namespace(this, true, null); } } /// public string FullName { get { return FullNameCreator.FullName(this, false, null, null); } } /// public string ReflectionFullName { get { return FullNameCreator.FullName(this, true, null, null); } } /// public string AssemblyQualifiedName { get { return FullNameCreator.AssemblyQualifiedName(this, null, null); } } /// public IAssembly DefinitionAssembly { get { return FullNameCreator.DefinitionAssembly(this); } } /// public IScope Scope { get { return FullNameCreator.Scope(this); } } /// public ITypeDefOrRef ScopeType { get { return FullNameCreator.ScopeType(this); } } /// public bool ContainsGenericParameter { get { return TypeHelper.ContainsGenericParameter(this); } } /// public ModuleDef Module { get { return FullNameCreator.OwnerModule(this); } } /// /// From column TypeSpec.Signature /// public TypeSig TypeSig { get { if (!typeSigAndExtraData_isInitialized) InitializeTypeSigAndExtraData(); return typeSig; } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif typeSig = value; if (!typeSigAndExtraData_isInitialized) GetTypeSigAndExtraData_NoLock(out extraData); typeSigAndExtraData_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// /// Gets/sets the extra data that was found after the signature /// public byte[] ExtraData { get { if (!typeSigAndExtraData_isInitialized) InitializeTypeSigAndExtraData(); return extraData; } set { if (!typeSigAndExtraData_isInitialized) InitializeTypeSigAndExtraData(); extraData = value; } } /// protected TypeSig typeSig; /// protected byte[] extraData; /// protected bool typeSigAndExtraData_isInitialized; void InitializeTypeSigAndExtraData() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (typeSigAndExtraData_isInitialized) return; typeSig = GetTypeSigAndExtraData_NoLock(out extraData); typeSigAndExtraData_isInitialized = true; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// Called to initialize protected virtual TypeSig GetTypeSigAndExtraData_NoLock(out byte[] extraData) { extraData = null; return null; } /// /// Gets all custom attributes /// public CustomAttributeCollection CustomAttributes { get { if (customAttributes == null) InitializeCustomAttributes(); return customAttributes; } } /// protected CustomAttributeCollection customAttributes; /// Initializes protected virtual void InitializeCustomAttributes() { Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null); } /// public bool HasCustomAttributes { get { return CustomAttributes.Count > 0; } } /// public int HasCustomDebugInformationTag { get { return 13; } } /// public bool HasCustomDebugInfos { get { return CustomDebugInfos.Count > 0; } } /// /// Gets all custom debug infos /// public ThreadSafe.IList CustomDebugInfos { get { if (customDebugInfos == null) InitializeCustomDebugInfos(); return customDebugInfos; } } /// protected ThreadSafe.IList customDebugInfos; /// Initializes protected virtual void InitializeCustomDebugInfos() { Interlocked.CompareExchange(ref customDebugInfos, ThreadSafeListCreator.Create(), null); } /// public override string ToString() { return FullName; } } /// /// A TypeSpec row created by the user and not present in the original .NET file /// public class TypeSpecUser : TypeSpec { /// /// Default constructor /// public TypeSpecUser() { } /// /// Constructor /// /// A type sig public TypeSpecUser(TypeSig typeSig) { this.typeSig = typeSig; this.extraData = null; this.typeSigAndExtraData_isInitialized = true; } } /// /// Created from a row in the TypeSpec table /// sealed class TypeSpecMD : TypeSpec, IMDTokenProviderMD { /// The module where this instance is located readonly ModuleDefMD readerModule; readonly uint origRid; readonly GenericParamContext gpContext; readonly uint signatureOffset; /// public uint OrigRid { get { return origRid; } } /// protected override TypeSig GetTypeSigAndExtraData_NoLock(out byte[] extraData) { var sig = readerModule.ReadTypeSignature(signatureOffset, gpContext, out extraData); if (sig != null) sig.Rid = origRid; return sig; } /// protected override void InitializeCustomAttributes() { var list = readerModule.MetaData.GetCustomAttributeRidList(Table.TypeSpec, origRid); var tmp = new CustomAttributeCollection((int)list.Length, list, (list2, index) => readerModule.ReadCustomAttribute(((RidList)list2)[index])); Interlocked.CompareExchange(ref customAttributes, tmp, null); } /// protected override void InitializeCustomDebugInfos() { var list = ThreadSafeListCreator.Create(); readerModule.InitializeCustomDebugInfos(new MDToken(MDToken.Table, origRid), gpContext, list); Interlocked.CompareExchange(ref customDebugInfos, list, null); } /// /// Constructor /// /// The module which contains this TypeSpec row /// Row ID /// Generic parameter context /// If is null /// If is invalid public TypeSpecMD(ModuleDefMD readerModule, uint rid, GenericParamContext gpContext) { #if DEBUG if (readerModule == null) throw new ArgumentNullException("readerModule"); if (readerModule.TablesStream.TypeSpecTable.IsInvalidRID(rid)) throw new BadImageFormatException(string.Format("TypeSpec rid {0} does not exist", rid)); #endif this.origRid = rid; this.rid = rid; this.readerModule = readerModule; this.gpContext = gpContext; this.signatureOffset = readerModule.TablesStream.ReadTypeSpecRow2(origRid); } } } dnlib-2.1_VS2010/src/DotNet/UTF8String.cs000066400000000000000000000615311325033663500176230ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Text; namespace dnlib.DotNet { /// /// Compares s /// public sealed class UTF8StringEqualityComparer : IEqualityComparer { /// /// The default instance /// public static readonly UTF8StringEqualityComparer Instance = new UTF8StringEqualityComparer(); /// public bool Equals(UTF8String x, UTF8String y) { return UTF8String.Equals(x, y); } /// public int GetHashCode(UTF8String obj) { return UTF8String.GetHashCode(obj); } } /// /// A UTF-8 encoded string where the original data is kept in memory to avoid conversions /// when the data is not really valid UTF-8 encoded data /// /// When comparing strings, a byte compare is performed. The reason is that this /// is what the CLR does when comparing strings in the #Strings stream. [DebuggerDisplay("{String}")] public sealed class UTF8String : IEquatable, IComparable { /// /// An empty /// public static readonly UTF8String Empty = new UTF8String(string.Empty); readonly byte[] data; string asString; /// /// Gets the value as a UTF8 decoded string. Only use it for display purposes, /// not for serialization. /// public string String { get { if (asString == null) asString = ConvertFromUTF8(data); return asString; } } /// /// Gets the original encoded data. Don't modify this data. /// public byte[] Data { get { return data; } } /// /// Gets the length of the this as a . I.e., it's the same as /// String.Length. /// /// public int Length { get { return String.Length; } } /// /// Gets the length of the raw data. It's the same as Data.Length /// /// public int DataLength { get { return data == null ? 0 : data.Length; } } /// /// Checks whether is null or if its data is null. /// /// The instance to check /// true if null or empty, false otherwise public static bool IsNull(UTF8String utf8) { return (object)utf8 == null || utf8.data == null; } /// /// Checks whether is null or if its data is null or the /// data is zero length. /// /// The instance to check /// true if null or empty, false otherwise public static bool IsNullOrEmpty(UTF8String utf8) { return (object)utf8 == null || utf8.data == null || utf8.data.Length == 0; } /// Implicit conversion from to public static implicit operator string(UTF8String s) { return UTF8String.ToSystemString(s); } /// Implicit conversion from to public static implicit operator UTF8String(string s) { return s == null ? null : new UTF8String(s); } /// /// Converts it to a /// /// The UTF-8 string instace or null /// A or null if is null public static string ToSystemString(UTF8String utf8) { if ((object)utf8 == null || utf8.data == null) return null; if (utf8.data.Length == 0) return string.Empty; return utf8.String; } /// /// Converts it to a or an empty string if is null /// /// The UTF-8 string instace or null /// A (never null) public static string ToSystemStringOrEmpty(UTF8String utf8) { return ToSystemString(utf8) ?? string.Empty; } /// /// Gets the hash code of a /// /// Input public static int GetHashCode(UTF8String utf8) { if (IsNullOrEmpty(utf8)) return 0; return Utils.GetHashCode(utf8.data); } /// public int CompareTo(UTF8String other) { return CompareTo(this, other); } /// /// Compares two instances (case sensitive) /// /// Instance #1 or null /// Instance #2 or null /// < 0 if a < b, 0 if a == b, > 0 if a > b public static int CompareTo(UTF8String a, UTF8String b) { return Utils.CompareTo((object)a == null ? null : a.data, (object)b == null ? null : b.data); } /// /// Compares two instances (case insensitive) /// /// Instance #1 or null /// Instance #2 or null /// < 0 if a < b, 0 if a == b, > 0 if a > b public static int CaseInsensitiveCompareTo(UTF8String a, UTF8String b) { if ((object)a == (object)b) return 0; var sa = ToSystemString(a); var sb = ToSystemString(b); if ((object)sa == (object)sb) return 0; if (sa == null) return -1; if (sb == null) return 1; return StringComparer.OrdinalIgnoreCase.Compare(sa, sb); } /// /// Compares two instances (case insensitive) /// /// Instance #1 or null /// Instance #2 or null /// true if equals, false otherwise public static bool CaseInsensitiveEquals(UTF8String a, UTF8String b) { return CaseInsensitiveCompareTo(a, b) == 0; } /// Overloaded operator public static bool operator ==(UTF8String left, UTF8String right) { return CompareTo(left, right) == 0; } /// Overloaded operator public static bool operator ==(UTF8String left, string right) { return ToSystemString(left) == right; } /// Overloaded operator public static bool operator ==(string left, UTF8String right) { return left == ToSystemString(right); } /// Overloaded operator public static bool operator !=(UTF8String left, UTF8String right) { return CompareTo(left, right) != 0; } /// Overloaded operator public static bool operator !=(UTF8String left, string right) { return ToSystemString(left) != right; } /// Overloaded operator public static bool operator !=(string left, UTF8String right) { return left != ToSystemString(right); } /// Overloaded operator public static bool operator >(UTF8String left, UTF8String right) { return CompareTo(left, right) > 0; } /// Overloaded operator public static bool operator <(UTF8String left, UTF8String right) { return CompareTo(left, right) < 0; } /// Overloaded operator public static bool operator >=(UTF8String left, UTF8String right) { return CompareTo(left, right) >= 0; } /// Overloaded operator public static bool operator <=(UTF8String left, UTF8String right) { return CompareTo(left, right) <= 0; } /// /// Constructor /// /// UTF-8 data that this instance now owns public UTF8String(byte[] data) { this.data = data; } /// /// Constructor /// /// The string public UTF8String(string s) : this(s == null ? null : Encoding.UTF8.GetBytes(s)) { } static string ConvertFromUTF8(byte[] data) { if (data == null) return null; try { return Encoding.UTF8.GetString(data); } catch { } return null; } /// /// Compares two instances /// /// First /// Second /// true if equals, false otherwise public static bool Equals(UTF8String a, UTF8String b) { return CompareTo(a, b) == 0; } /// public bool Equals(UTF8String other) { return CompareTo(this, other) == 0; } /// public override bool Equals(object obj) { var other = obj as UTF8String; if ((object)other == null) return false; return CompareTo(this, other) == 0; } /// /// Checks whether exists in this string /// /// Value to find /// true if exists in string or is the /// empty string, else false public bool Contains(string value) { return String.Contains(value); } /// /// Checks whether matches the end of this string /// /// Value /// public bool EndsWith(string value) { return String.EndsWith(value); } /// /// Checks whether matches the end of this string /// /// Value /// true to ignore case /// Culture info /// public bool EndsWith(string value, bool ignoreCase, CultureInfo culture) { return String.EndsWith(value, ignoreCase, culture); } /// /// Checks whether matches the end of this string /// /// Value /// Comparison type /// public bool EndsWith(string value, StringComparison comparisonType) { return String.EndsWith(value, comparisonType); } /// /// Checks whether matches the beginning of this string /// /// Value /// public bool StartsWith(string value) { return String.StartsWith(value); } /// /// Checks whether matches the beginning of this string /// /// Value /// true to ignore case /// Culture info /// public bool StartsWith(string value, bool ignoreCase, CultureInfo culture) { return String.StartsWith(value, ignoreCase, culture); } /// /// Checks whether matches the beginning of this string /// /// Value /// Comparison type /// public bool StartsWith(string value, StringComparison comparisonType) { return String.StartsWith(value, comparisonType); } /// /// Compares this instance with /// /// Other string /// < 0 if a < b, 0 if a == b, > 0 if a > b public int CompareTo(string strB) { return String.CompareTo(strB); } /// /// Returns the index of the first character in this string /// /// Character /// The index of or -1 if not found public int IndexOf(char value) { return String.IndexOf(value); } /// /// Returns the index of the first character in this string /// starting from index /// /// Character /// Start index /// The index of or -1 if not found public int IndexOf(char value, int startIndex) { return String.IndexOf(value, startIndex); } /// /// Returns the index of the first character in this string /// starting from index for max /// characters. /// /// Character /// Start index /// Max number of chars to scan /// The index of or -1 if not found public int IndexOf(char value, int startIndex, int count) { return String.IndexOf(value, startIndex, count); } /// /// Returns the index of the first sub string in this string /// /// String /// The index of or -1 if not found public int IndexOf(string value) { return String.IndexOf(value); } /// /// Returns the index of the first sub string in this string /// starting from index /// /// String /// Start index /// The index of or -1 if not found public int IndexOf(string value, int startIndex) { return String.IndexOf(value, startIndex); } /// /// Returns the index of the first sub string in this string /// starting from index for max /// characters. /// /// String /// Start index /// Max number of chars to scan /// The index of or -1 if not found public int IndexOf(string value, int startIndex, int count) { return String.IndexOf(value, startIndex, count); } /// /// Returns the index of the first sub string in this string /// starting from index for max /// characters. /// /// String /// Start index /// Max number of chars to scan /// Comparison type /// The index of or -1 if not found public int IndexOf(string value, int startIndex, int count, StringComparison comparisonType) { return String.IndexOf(value, startIndex, count, comparisonType); } /// /// Returns the index of the first sub string in this string /// starting from index /// /// String /// Start index /// Comparison type /// The index of or -1 if not found public int IndexOf(string value, int startIndex, StringComparison comparisonType) { return String.IndexOf(value, startIndex, comparisonType); } /// /// Returns the index of the first sub string in this string /// /// String /// Comparison type /// The index of or -1 if not found public int IndexOf(string value, StringComparison comparisonType) { return String.IndexOf(value, comparisonType); } /// /// Returns the index of the last character in this string /// /// Character /// The index of or -1 if not found public int LastIndexOf(char value) { return String.LastIndexOf(value); } /// /// Returns the index of the last character in this string /// starting from index /// /// Character /// Start index /// The index of or -1 if not found public int LastIndexOf(char value, int startIndex) { return String.LastIndexOf(value, startIndex); } /// /// Returns the index of the last character in this string /// starting from index for max /// characters. /// /// Character /// Start index /// Max number of chars to scan /// The index of or -1 if not found public int LastIndexOf(char value, int startIndex, int count) { return String.LastIndexOf(value, startIndex, count); } /// /// Returns the index of the last sub string in this string /// /// String /// The index of or -1 if not found public int LastIndexOf(string value) { return String.LastIndexOf(value); } /// /// Returns the index of the last sub string in this string /// starting from index /// /// String /// Start index /// The index of or -1 if not found public int LastIndexOf(string value, int startIndex) { return String.LastIndexOf(value, startIndex); } /// /// Returns the index of the last sub string in this string /// starting from index for max /// characters. /// /// String /// Start index /// Max number of chars to scan /// The index of or -1 if not found public int LastIndexOf(string value, int startIndex, int count) { return String.LastIndexOf(value, startIndex, count); } /// /// Returns the index of the last sub string in this string /// starting from index for max /// characters. /// /// String /// Start index /// Max number of chars to scan /// Comparison type /// The index of or -1 if not found public int LastIndexOf(string value, int startIndex, int count, StringComparison comparisonType) { return String.LastIndexOf(value, startIndex, count, comparisonType); } /// /// Returns the index of the last sub string in this string /// starting from index /// /// String /// Start index /// Comparison type /// The index of or -1 if not found public int LastIndexOf(string value, int startIndex, StringComparison comparisonType) { return String.LastIndexOf(value, startIndex, comparisonType); } /// /// Returns the index of the last sub string in this string /// /// String /// Comparison type /// The index of or -1 if not found public int LastIndexOf(string value, StringComparison comparisonType) { return String.LastIndexOf(value, comparisonType); } /// /// Inserts string at a index /// /// Start index /// Value to insert /// A new instance with the inserted at position /// public UTF8String Insert(int startIndex, string value) { return new UTF8String(String.Insert(startIndex, value)); } /// /// Removes all characters starting from position /// /// Start index /// A new instance public UTF8String Remove(int startIndex) { return new UTF8String(String.Remove(startIndex)); } /// /// Removes characters starting from position /// /// /// Start index /// Number of characters to remove /// A new instance public UTF8String Remove(int startIndex, int count) { return new UTF8String(String.Remove(startIndex, count)); } /// /// Replaces all characters with /// /// Character to find /// Character to replace all /// A new instance public UTF8String Replace(char oldChar, char newChar) { return new UTF8String(String.Replace(oldChar, newChar)); } /// /// Replaces all sub strings with /// /// Sub string to find /// Sub string to replace all /// A new instance public UTF8String Replace(string oldValue, string newValue) { return new UTF8String(String.Replace(oldValue, newValue)); } /// /// Returns a sub string of this string starting at offset /// /// Start index /// A new instance public UTF8String Substring(int startIndex) { return new UTF8String(String.Substring(startIndex)); } /// /// Returns a sub string of this string starting at offset . /// Length of sub string is . /// /// Start index /// Length of sub string /// A new instance public UTF8String Substring(int startIndex, int length) { return new UTF8String(String.Substring(startIndex, length)); } /// /// Returns the lower case version of this string /// /// A new instance public UTF8String ToLower() { return new UTF8String(String.ToLower()); } /// /// Returns the lower case version of this string /// /// Culture info /// A new instance public UTF8String ToLower(CultureInfo culture) { return new UTF8String(String.ToLower(culture)); } /// /// Returns the lower case version of this string using the invariant culture /// /// A new instance public UTF8String ToLowerInvariant() { return new UTF8String(String.ToLowerInvariant()); } /// /// Returns the upper case version of this string /// /// A new instance public UTF8String ToUpper() { return new UTF8String(String.ToUpper()); } /// /// Returns the upper case version of this string /// /// Culture info /// A new instance public UTF8String ToUpper(CultureInfo culture) { return new UTF8String(String.ToUpper(culture)); } /// /// Returns the upper case version of this string using the invariant culture /// /// A new instance public UTF8String ToUpperInvariant() { return new UTF8String(String.ToUpperInvariant()); } /// /// Removes all leading and trailing whitespace characters /// /// A new instance public UTF8String Trim() { return new UTF8String(String.Trim()); } /// public override int GetHashCode() { return UTF8String.GetHashCode(this); } /// public override string ToString() { return String; } } } dnlib-2.1_VS2010/src/DotNet/Utils.cs000066400000000000000000000321451325033663500170050ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using System.Text; namespace dnlib.DotNet { /// /// Compares byte arrays /// public sealed class ByteArrayEqualityComparer : IEqualityComparer { /// /// Default instance /// public static readonly ByteArrayEqualityComparer Instance = new ByteArrayEqualityComparer(); /// public bool Equals(byte[] x, byte[] y) { return Utils.Equals(x, y); } /// public int GetHashCode(byte[] obj) { return Utils.GetHashCode(obj); } } static class Utils { /// /// Returns an assembly name string /// /// Simple assembly name /// Version or null /// Culture or null /// Public key / public key token or null /// Assembly attributes /// An assembly name string internal static string GetAssemblyNameString(UTF8String name, Version version, UTF8String culture, PublicKeyBase publicKey, AssemblyAttributes attributes) { var sb = new StringBuilder(); foreach (var c in UTF8String.ToSystemStringOrEmpty(name)) { if (c == ',' || c == '=') sb.Append('\\'); sb.Append(c); } if (version != null) { sb.Append(", Version="); sb.Append(CreateVersionWithNoUndefinedValues(version).ToString()); } if ((object)culture != null) { sb.Append(", Culture="); sb.Append(UTF8String.IsNullOrEmpty(culture) ? "neutral" : culture.String); } sb.Append(", "); sb.Append(publicKey == null || publicKey is PublicKeyToken ? "PublicKeyToken=" : "PublicKey="); sb.Append(publicKey == null ? "null" : publicKey.ToString()); if ((attributes & AssemblyAttributes.Retargetable) != 0) sb.Append(", Retargetable=Yes"); if ((attributes & AssemblyAttributes.ContentType_Mask) == AssemblyAttributes.ContentType_WindowsRuntime) sb.Append(", ContentType=WindowsRuntime"); return sb.ToString(); } /// /// Convert a byte[] to a /// /// All bytes /// true if output should be in upper case hex /// as a hex string internal static string ToHex(byte[] bytes, bool upper) { if (bytes == null) return ""; var chars = new char[bytes.Length * 2]; for (int i = 0, j = 0; i < bytes.Length; i++) { byte b = bytes[i]; chars[j++] = ToHexChar(b >> 4, upper); chars[j++] = ToHexChar(b & 0x0F, upper); } return new string(chars); } static char ToHexChar(int val, bool upper) { if (0 <= val && val <= 9) return (char)(val + (int)'0'); return (char)(val - 10 + (upper ? (int)'A' : (int)'a')); } /// /// Converts a hex string to a byte[] /// /// A string with an even number of hex characters /// converted to a byte[] or null /// if is invalid internal static byte[] ParseBytes(string hexString) { try { if (hexString.Length % 2 != 0) return null; var bytes = new byte[hexString.Length / 2]; for (int i = 0; i < hexString.Length; i += 2) { int upper = TryParseHexChar(hexString[i]); int lower = TryParseHexChar(hexString[i + 1]); if (upper < 0 || lower < 0) return null; bytes[i / 2] = (byte)((upper << 4) | lower); } return bytes; } catch { return null; } } /// /// Converts a character to a hex digit /// /// Hex character /// 0x00-0x0F if successful, -1 if is not /// a valid hex digit static int TryParseHexChar(char c) { if ('0' <= c && c <= '9') return (ushort)c - (ushort)'0'; if ('a' <= c && c <= 'f') return 10 + (ushort)c - (ushort)'a'; if ('A' <= c && c <= 'F') return 10 + (ushort)c - (ushort)'A'; return -1; } /// /// Compares two byte arrays /// /// Byte array #1 /// Byte array #2 /// < 0 if a < b, 0 if a == b, > 0 if a > b internal static int CompareTo(byte[] a, byte[] b) { if (a == b) return 0; if (a == null) return -1; if (b == null) return 1; int count = Math.Min(a.Length, b.Length); for (int i = 0; i < count; i++) { var ai = a[i]; var bi = b[i]; if (ai < bi) return -1; if (ai > bi) return 1; } return a.Length.CompareTo(b.Length); } /// /// Checks whether two byte arrays are equal /// /// First /// Second /// true if same, false otherwise internal static bool Equals(byte[] a, byte[] b) { return CompareTo(a, b) == 0; } /// /// Gets the hash code of a byte array /// /// Byte array /// The hash code internal static int GetHashCode(byte[] a) { if (a == null || a.Length == 0) return 0; int count = Math.Min(a.Length / 2, 20); if (count == 0) count = 1; uint hash = 0; for (int i = 0, j = a.Length - 1; i < count; i++, j--) { hash ^= a[i] | ((uint)a[j] << 8); hash = (hash << 13) | (hash >> 19); } return (int)hash; } /// /// Compares two versions /// /// This differs from if the build /// and/or revision numbers haven't been initialized or if one of the args is null. /// /// Version #1 or null to be treated as v0.0.0.0 /// Version #2 or null to be treated as v0.0.0.0 /// < 0 if a < b, 0 if a == b, > 0 if a > b internal static int CompareTo(Version a, Version b) { if (a == null) a = new Version(); if (b == null) b = new Version(); if (a.Major != b.Major) return a.Major.CompareTo(b.Major); if (a.Minor != b.Minor) return a.Minor.CompareTo(b.Minor); if (GetDefaultVersionValue(a.Build) != GetDefaultVersionValue(b.Build)) return GetDefaultVersionValue(a.Build).CompareTo(GetDefaultVersionValue(b.Build)); return GetDefaultVersionValue(a.Revision).CompareTo(GetDefaultVersionValue(b.Revision)); } /// /// Checks whether two versions are the same /// /// This differs from if the build /// and/or revision numbers haven't been initialized or if one of the args is null. /// /// Version #1 or null to be treated as v0.0.0.0 /// Version #2 or null to be treated as v0.0.0.0 /// true if same, false otherwise internal static bool Equals(Version a, Version b) { return CompareTo(a, b) == 0; } /// /// Creates a new instance with no undefined version values (eg. /// the build and revision values won't be -1). /// /// A instance /// A new instance internal static Version CreateVersionWithNoUndefinedValues(Version a) { if (a == null) return new Version(0, 0, 0, 0); return new Version(a.Major, a.Minor, GetDefaultVersionValue(a.Build), GetDefaultVersionValue(a.Revision)); } static int GetDefaultVersionValue(int val) { return val == -1 ? 0 : val; } /// /// Parses a version string /// /// Version string /// A new or null if /// is an invalid version internal static Version ParseVersion(string versionString) { try { return Utils.CreateVersionWithNoUndefinedValues(new Version(versionString)); } catch { return null; } } /// /// Compares two locales (cultures) /// /// First /// Second /// < 0 if a < b, 0 if a == b, > 0 if a > b internal static int LocaleCompareTo(UTF8String a, UTF8String b) { return GetCanonicalLocale(a).CompareTo(GetCanonicalLocale(b)); } /// /// Compares two locales (cultures) /// /// First /// Second /// true if same, false otherwise internal static bool LocaleEquals(UTF8String a, UTF8String b) { return LocaleCompareTo(a, b) == 0; } /// /// Compares two locales (cultures) /// /// First /// Second /// < 0 if a < b, 0 if a == b, > 0 if a > b internal static int LocaleCompareTo(UTF8String a, string b) { return GetCanonicalLocale(a).CompareTo(GetCanonicalLocale(b)); } /// /// Compares two locales (cultures) /// /// First /// Second /// true if same, false otherwise internal static bool LocaleEquals(UTF8String a, string b) { return LocaleCompareTo(a, b) == 0; } /// /// Gets the hash code of a locale /// /// Value /// The hash code internal static int GetHashCodeLocale(UTF8String a) { return GetCanonicalLocale(a).GetHashCode(); } static string GetCanonicalLocale(UTF8String locale) { return GetCanonicalLocale(UTF8String.ToSystemStringOrEmpty(locale)); } static string GetCanonicalLocale(string locale) { var s = locale.ToUpperInvariant(); if (s == "NEUTRAL") s = string.Empty; return s; } /// /// Align up /// /// Value /// Alignment public static uint AlignUp(uint v, uint alignment) { return (v + alignment - 1) & ~(alignment - 1); } /// /// Align up /// /// Value /// Alignment public static int AlignUp(int v, uint alignment) { return (int)AlignUp((uint)v, alignment); } /// /// Gets length of compressed integer /// /// Integer /// Size of compressed integer in bytes (1, 2 or 4 bytes) /// can't be compressed (too big) public static int GetCompressedUInt32Length(uint value) { if (value <= 0x7F) return 1; if (value <= 0x3FFF) return 2; if (value <= 0x1FFFFFFF) return 4; throw new ArgumentOutOfRangeException("UInt32 value can't be compressed"); } /// /// Writes a compressed /// /// Writer /// Value /// can't be compressed (too big) public static void WriteCompressedUInt32(this BinaryWriter writer, uint value) { if (value <= 0x7F) writer.Write((byte)value); else if (value <= 0x3FFF) { writer.Write((byte)((value >> 8) | 0x80)); writer.Write((byte)value); } else if (value <= 0x1FFFFFFF) { writer.Write((byte)((value >> 24) | 0xC0)); writer.Write((byte)(value >> 16)); writer.Write((byte)(value >> 8)); writer.Write((byte)value); } else throw new ArgumentOutOfRangeException("UInt32 value can't be compressed"); } /// /// Writes a compressed /// /// Writer /// Value /// can't be compressed (too big/small) public static void WriteCompressedInt32(this BinaryWriter writer, int value) { // This is almost identical to compressing a UInt32, except that we first // recode value so the sign bit is in bit 0. Then we compress it the same // way a UInt32 is compressed. uint sign = (uint)value >> 31; if (-0x40 <= value && value <= 0x3F) { uint v = (uint)((value & 0x3F) << 1) | sign; writer.Write((byte)v); } else if (-0x2000 <= value && value <= 0x1FFF) { uint v = ((uint)(value & 0x1FFF) << 1) | sign; writer.Write((byte)((v >> 8) | 0x80)); writer.Write((byte)v); } else if (-0x10000000 <= value && value <= 0x0FFFFFFF) { uint v = ((uint)(value & 0x0FFFFFFF) << 1) | sign; writer.Write((byte)((v >> 24) | 0xC0)); writer.Write((byte)(v >> 16)); writer.Write((byte)(v >> 8)); writer.Write((byte)v); } else throw new ArgumentOutOfRangeException("Int32 value can't be compressed"); } } } dnlib-2.1_VS2010/src/DotNet/VTableFixups.cs000066400000000000000000000132271325033663500202610ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using dnlib.PE; using dnlib.IO; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.DotNet { /// /// All native vtables /// [DebuggerDisplay("RVA = {RVA}, Count = {VTables.Count}")] public sealed class VTableFixups : IEnumerable { RVA rva; ThreadSafe.IList vtables; /// /// Gets/sets the RVA of the vtable fixups /// public RVA RVA { get { return rva; } set { rva = value; } } /// /// Gets all s /// public ThreadSafe.IList VTables { get { return vtables; } } /// /// Default constructor /// public VTableFixups() { this.vtables = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Module public VTableFixups(ModuleDefMD module) { Initialize(module); } void Initialize(ModuleDefMD module) { var info = module.MetaData.ImageCor20Header.VTableFixups; if (info.VirtualAddress == 0 || info.Size == 0) { this.vtables = ThreadSafeListCreator.Create(); return; } this.rva = info.VirtualAddress; this.vtables = ThreadSafeListCreator.Create((int)info.Size / 8); var peImage = module.MetaData.PEImage; using (var reader = peImage.CreateFullStream()) { reader.Position = (long)peImage.ToFileOffset(info.VirtualAddress); long endPos = reader.Position + info.Size; while (reader.Position + 8 <= endPos && reader.CanRead(8)) { RVA tableRva = (RVA)reader.ReadUInt32(); int numSlots = reader.ReadUInt16(); var flags = (VTableFlags)reader.ReadUInt16(); var vtable = new VTable(tableRva, flags, numSlots); vtables.Add(vtable); var pos = reader.Position; reader.Position = (long)peImage.ToFileOffset(tableRva); int slotSize = vtable.Is64Bit ? 8 : 4; while (numSlots-- > 0 && reader.CanRead(slotSize)) { vtable.Methods.Add(module.ResolveToken(reader.ReadUInt32()) as IMethod); if (slotSize == 8) reader.ReadUInt32(); } reader.Position = pos; } } } /// public IEnumerator GetEnumerator() { return vtables.GetEnumerator(); } /// System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } /// /// See COR_VTABLE_XXX in CorHdr.h /// [Flags] public enum VTableFlags : ushort { /// /// 32-bit vtable slots /// _32Bit = 0x01, /// /// 64-bit vtable slots /// _64Bit = 0x02, /// /// Transition from unmanaged code /// FromUnmanaged = 0x04, /// /// Also retain app domain /// FromUnmanagedRetainAppDomain = 0x08, /// /// Call most derived method /// CallMostDerived = 0x10, } /// /// One VTable accessed by native code /// public sealed class VTable : IEnumerable { RVA rva; VTableFlags flags; readonly ThreadSafe.IList methods; /// /// Gets/sets the of this vtable /// public RVA RVA { get { return rva; } set { rva = value; } } /// /// Gets/sets the flags /// public VTableFlags Flags { get { return flags; } set { flags = value; } } /// /// true if each vtable slot is 32 bits in size /// public bool Is32Bit { get { return (flags & VTableFlags._32Bit) != 0; } } /// /// true if each vtable slot is 64 bits in size /// public bool Is64Bit { get { return (flags & VTableFlags._64Bit) != 0; } } /// /// Gets the vtable methods /// public ThreadSafe.IList Methods { get { return methods; } } /// /// Default constructor /// public VTable() { this.methods = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// Flags public VTable(VTableFlags flags) { this.flags = flags; this.methods = ThreadSafeListCreator.Create(); } /// /// Constructor /// /// RVA of this vtable /// Flgas /// Number of methods in vtable public VTable(RVA rva, VTableFlags flags, int numSlots) { this.rva = rva; this.flags = flags; this.methods = ThreadSafeListCreator.Create(numSlots); } /// /// Constructor /// /// RVA of this vtable /// Flgas /// Vtable methods public VTable(RVA rva, VTableFlags flags, IEnumerable methods) { this.rva = rva; this.flags = flags; this.methods = ThreadSafeListCreator.Create(methods); } /// public IEnumerator GetEnumerator() { return methods.GetEnumerator(); } /// System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } /// public override string ToString() { if (methods.Count == 0) return string.Format("{0} {1:X8}", methods.Count, (uint)rva); return string.Format("{0} {1:X8} {2}", methods.Count, (uint)rva, methods.Get(0, null)); } } } dnlib-2.1_VS2010/src/DotNet/VariantType.cs000066400000000000000000000040501325033663500201450ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// Variant type (VT_XXX in the Windows SDK) /// public enum VariantType : uint { /// Empty = 0, /// None = 0, /// Null = 1, /// I2 = 2, /// I4 = 3, /// R4 = 4, /// R8 = 5, /// CY = 6, /// Date = 7, /// BStr = 8, /// Dispatch = 9, /// Error = 10, /// Bool = 11, /// Variant = 12, /// Unknown = 13, /// Decimal = 14, /// I1 = 16, /// UI1 = 17, /// UI2 = 18, /// UI4 = 19, /// I8 = 20, /// UI8 = 21, /// Int = 22, /// UInt = 23, /// Void = 24, /// HResult = 25, /// Ptr = 26, /// SafeArray = 27, /// CArray = 28, /// UserDefined = 29, /// LPStr = 30, /// LPWStr = 31, /// Record = 36, /// IntPtr = 37, /// UIntPtr = 38, /// FileTime = 64, /// Blob = 65, /// Stream = 66, /// Storage = 67, /// StreamedObject = 68, /// StoredObject = 69, /// BlobObject = 70, /// CF = 71, /// CLSID = 72, /// VersionedStream = 73, /// BStrBlob = 0x0FFF, /// Vector = 0x1000, /// Array = 0x2000, /// ByRef = 0x4000, /// Reserved = 0x8000, /// Illegal = 0xFFFF, /// IllegalMasked = 0x0FFF, /// TypeMask = 0x0FFF, /// This wasn't present in the blob NotInitialized = 0xFFFFFFFF, } } dnlib-2.1_VS2010/src/DotNet/WinMDHelpers.cs000066400000000000000000000575211325033663500202130ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; namespace dnlib.DotNet { enum ClrAssembly { Mscorlib, SystemNumericsVectors, SystemObjectModel, SystemRuntime, SystemRuntimeInteropServicesWindowsRuntime, SystemRuntimeWindowsRuntime, SystemRuntimeWindowsRuntimeUIXaml, } static class WinMDHelpers { struct ClassName : IEquatable { public readonly UTF8String Namespace; public readonly UTF8String Name; // Not used when comparing for equality etc public readonly bool IsValueType; public ClassName(UTF8String ns, UTF8String name, bool isValueType = false) { this.Namespace = ns; this.Name = name; this.IsValueType = isValueType; } public ClassName(string ns, string name, bool isValueType = false) { this.Namespace = ns; this.Name = name; this.IsValueType = isValueType; } public static bool operator ==(ClassName a, ClassName b) { return a.Equals(b); } public static bool operator !=(ClassName a, ClassName b) { return !a.Equals(b); } public bool Equals(ClassName other) { // Don't check IsValueType return UTF8String.Equals(Namespace, other.Namespace) && UTF8String.Equals(Name, other.Name); } public override bool Equals(object obj) { if (!(obj is ClassName)) return false; return Equals((ClassName)obj); } public override int GetHashCode() { // Don't use IsValueType return UTF8String.GetHashCode(Namespace) ^ UTF8String.GetHashCode(Name); } public override string ToString() { return string.Format("{0}.{1}", Namespace, Name); } } sealed class ProjectedClass { public readonly ClassName WinMDClass; public readonly ClassName ClrClass; public readonly ClrAssembly ClrAssembly; public readonly ClrAssembly ContractAssembly; public ProjectedClass(string mdns, string mdname, string clrns, string clrname, ClrAssembly clrAsm, ClrAssembly contractAsm, bool winMDValueType, bool clrValueType) { this.WinMDClass = new ClassName(mdns, mdname, winMDValueType); this.ClrClass = new ClassName(clrns, clrname, clrValueType); this.ClrAssembly = clrAsm; this.ContractAssembly = contractAsm; } public override string ToString() { return string.Format("{0} <-> {1}, {2}", WinMDClass, ClrClass, CreateAssembly(null, ContractAssembly)); } } // See https://github.com/dotnet/coreclr/blob/master/src/inc/winrtprojectedtypes.h // To generate this code replace the contents of src/inc/winrtprojectedtypes.h with: // DEFINE_PROJECTED_ENUM // => DEFINE_PROJECTED_STRUCT // ^DEFINE_PROJECTED\w*_STRUCT\s*\(("[^"]+"),\s*("[^"]+"),\s*("[^"]+"),\s*("[^"]+"),\s*(\w+),\s*(\w+).*$ // => \t\t\tnew ProjectedClass(\1, \2, \3, \4, ClrAssembly.\5, ClrAssembly.\6, true, true), // ^DEFINE_PROJECTED\w+\s*\(("[^"]+"),\s*("[^"]+"),\s*("[^"]+"),\s*("[^"]+"),\s*(\w+),\s*(\w+).*$ // => \t\t\tnew ProjectedClass(\1, \2, \3, \4, ClrAssembly.\5, ClrAssembly.\6, false, false), // Sometimes the types aren't both structs or both classes. Known cases: // IReference`1 (class) vs Nullable`1 (struct) // IKeyValuePair`2 (class) vs KeyValuePair`2 (struct) // TypeName (struct) vs Type (class) // HResult (struct) vs Exception (class) // See md/winmd/adapter.cpp WinMDAdapter::RewriteTypeInSignature() or check the types // in a decompiler. static readonly ProjectedClass[] ProjectedClasses = new ProjectedClass[] { new ProjectedClass("Windows.Foundation.Metadata", "AttributeUsageAttribute", "System", "AttributeUsageAttribute", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, false, false), new ProjectedClass("Windows.Foundation.Metadata", "AttributeTargets", "System", "AttributeTargets", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, true, true), new ProjectedClass("Windows.UI", "Color", "Windows.UI", "Color", ClrAssembly.SystemRuntimeWindowsRuntime, ClrAssembly.SystemRuntimeWindowsRuntime, true, true), new ProjectedClass("Windows.Foundation", "DateTime", "System", "DateTimeOffset", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, true, true), new ProjectedClass("Windows.Foundation", "EventHandler`1", "System", "EventHandler`1", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, false, false), new ProjectedClass("Windows.Foundation", "EventRegistrationToken", "System.Runtime.InteropServices.WindowsRuntime", "EventRegistrationToken", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntimeInteropServicesWindowsRuntime, true, true), new ProjectedClass("Windows.Foundation", "HResult", "System", "Exception", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, true, false), new ProjectedClass("Windows.Foundation", "IReference`1", "System", "Nullable`1", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, false, true), new ProjectedClass("Windows.Foundation", "Point", "Windows.Foundation", "Point", ClrAssembly.SystemRuntimeWindowsRuntime, ClrAssembly.SystemRuntimeWindowsRuntime, true, true), new ProjectedClass("Windows.Foundation", "Rect", "Windows.Foundation", "Rect", ClrAssembly.SystemRuntimeWindowsRuntime, ClrAssembly.SystemRuntimeWindowsRuntime, true, true), new ProjectedClass("Windows.Foundation", "Size", "Windows.Foundation", "Size", ClrAssembly.SystemRuntimeWindowsRuntime, ClrAssembly.SystemRuntimeWindowsRuntime, true, true), new ProjectedClass("Windows.Foundation", "TimeSpan", "System", "TimeSpan", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, true, true), new ProjectedClass("Windows.Foundation", "Uri", "System", "Uri", ClrAssembly.SystemRuntime, ClrAssembly.SystemRuntime, false, false), new ProjectedClass("Windows.Foundation", "IClosable", "System", "IDisposable", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, false, false), new ProjectedClass("Windows.Foundation.Collections", "IIterable`1", "System.Collections.Generic", "IEnumerable`1", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, false, false), new ProjectedClass("Windows.Foundation.Collections", "IVector`1", "System.Collections.Generic", "IList`1", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, false, false), new ProjectedClass("Windows.Foundation.Collections", "IVectorView`1", "System.Collections.Generic", "IReadOnlyList`1", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, false, false), new ProjectedClass("Windows.Foundation.Collections", "IMap`2", "System.Collections.Generic", "IDictionary`2", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, false, false), new ProjectedClass("Windows.Foundation.Collections", "IMapView`2", "System.Collections.Generic", "IReadOnlyDictionary`2", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, false, false), new ProjectedClass("Windows.Foundation.Collections", "IKeyValuePair`2", "System.Collections.Generic", "KeyValuePair`2", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, false, true), new ProjectedClass("Windows.UI.Xaml.Input", "ICommand", "System.Windows.Input", "ICommand", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, false, false), new ProjectedClass("Windows.UI.Xaml.Interop", "IBindableIterable", "System.Collections", "IEnumerable", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, false, false), new ProjectedClass("Windows.UI.Xaml.Interop", "IBindableVector", "System.Collections", "IList", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, false, false), new ProjectedClass("Windows.UI.Xaml.Interop", "INotifyCollectionChanged", "System.Collections.Specialized", "INotifyCollectionChanged", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, false, false), new ProjectedClass("Windows.UI.Xaml.Interop", "NotifyCollectionChangedEventHandler", "System.Collections.Specialized", "NotifyCollectionChangedEventHandler", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, false, false), new ProjectedClass("Windows.UI.Xaml.Interop", "NotifyCollectionChangedEventArgs", "System.Collections.Specialized", "NotifyCollectionChangedEventArgs", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, false, false), new ProjectedClass("Windows.UI.Xaml.Interop", "NotifyCollectionChangedAction", "System.Collections.Specialized", "NotifyCollectionChangedAction", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, true, true), new ProjectedClass("Windows.UI.Xaml.Data", "INotifyPropertyChanged", "System.ComponentModel", "INotifyPropertyChanged", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, false, false), new ProjectedClass("Windows.UI.Xaml.Data", "PropertyChangedEventHandler", "System.ComponentModel", "PropertyChangedEventHandler", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, false, false), new ProjectedClass("Windows.UI.Xaml.Data", "PropertyChangedEventArgs", "System.ComponentModel", "PropertyChangedEventArgs", ClrAssembly.SystemObjectModel, ClrAssembly.SystemObjectModel, false, false), new ProjectedClass("Windows.UI.Xaml", "CornerRadius", "Windows.UI.Xaml", "CornerRadius", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, true, true), new ProjectedClass("Windows.UI.Xaml", "Duration", "Windows.UI.Xaml", "Duration", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, true, true), new ProjectedClass("Windows.UI.Xaml", "DurationType", "Windows.UI.Xaml", "DurationType", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, true, true), new ProjectedClass("Windows.UI.Xaml", "GridLength", "Windows.UI.Xaml", "GridLength", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, true, true), new ProjectedClass("Windows.UI.Xaml", "GridUnitType", "Windows.UI.Xaml", "GridUnitType", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, true, true), new ProjectedClass("Windows.UI.Xaml", "Thickness", "Windows.UI.Xaml", "Thickness", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, true, true), new ProjectedClass("Windows.UI.Xaml.Interop", "TypeName", "System", "Type", ClrAssembly.Mscorlib, ClrAssembly.SystemRuntime, true, false), new ProjectedClass("Windows.UI.Xaml.Controls.Primitives", "GeneratorPosition", "Windows.UI.Xaml.Controls.Primitives", "GeneratorPosition", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, true, true), new ProjectedClass("Windows.UI.Xaml.Media", "Matrix", "Windows.UI.Xaml.Media", "Matrix", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, true, true), new ProjectedClass("Windows.UI.Xaml.Media.Animation", "KeyTime", "Windows.UI.Xaml.Media.Animation", "KeyTime", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, true, true), new ProjectedClass("Windows.UI.Xaml.Media.Animation", "RepeatBehavior", "Windows.UI.Xaml.Media.Animation", "RepeatBehavior", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, true, true), new ProjectedClass("Windows.UI.Xaml.Media.Animation", "RepeatBehaviorType", "Windows.UI.Xaml.Media.Animation", "RepeatBehaviorType", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, true, true), new ProjectedClass("Windows.UI.Xaml.Media.Media3D", "Matrix3D", "Windows.UI.Xaml.Media.Media3D", "Matrix3D", ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml, true, true), new ProjectedClass("Windows.Foundation.Numerics", "Vector2", "System.Numerics", "Vector2", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, true, true), new ProjectedClass("Windows.Foundation.Numerics", "Vector3", "System.Numerics", "Vector3", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, true, true), new ProjectedClass("Windows.Foundation.Numerics", "Vector4", "System.Numerics", "Vector4", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, true, true), new ProjectedClass("Windows.Foundation.Numerics", "Matrix3x2", "System.Numerics", "Matrix3x2", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, true, true), new ProjectedClass("Windows.Foundation.Numerics", "Matrix4x4", "System.Numerics", "Matrix4x4", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, true, true), new ProjectedClass("Windows.Foundation.Numerics", "Plane", "System.Numerics", "Plane", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, true, true), new ProjectedClass("Windows.Foundation.Numerics", "Quaternion", "System.Numerics", "Quaternion", ClrAssembly.SystemNumericsVectors, ClrAssembly.SystemNumericsVectors, true, true), }; static readonly Dictionary winMDToCLR = new Dictionary(); static WinMDHelpers() { foreach (var projClass in ProjectedClasses) winMDToCLR.Add(projClass.WinMDClass, projClass); } static AssemblyRef ToCLR(ModuleDef module, ref UTF8String ns, ref UTF8String name) { ProjectedClass pc; if (!winMDToCLR.TryGetValue(new ClassName(ns, name), out pc)) return null; ns = pc.ClrClass.Namespace; name = pc.ClrClass.Name; return CreateAssembly(module, pc.ContractAssembly); } static AssemblyRef CreateAssembly(ModuleDef module, ClrAssembly clrAsm) { var mscorlib = module == null ? null : module.CorLibTypes.AssemblyRef; var asm = new AssemblyRefUser(GetName(clrAsm), contractAsmVersion, new PublicKeyToken(GetPublicKeyToken(clrAsm)), UTF8String.Empty); if (mscorlib != null && mscorlib.Name == mscorlibName && mscorlib.Version != invalidWinMDVersion) asm.Version = mscorlib.Version; var mod = module as ModuleDefMD; if (mod != null) { Version ver = null; foreach (var asmRef in mod.GetAssemblyRefs()) { if (asmRef.IsContentTypeWindowsRuntime) continue; if (asmRef.Name != asm.Name) continue; if (asmRef.Culture != asm.Culture) continue; if (!PublicKeyBase.TokenEquals(asmRef.PublicKeyOrToken, asm.PublicKeyOrToken)) continue; if (asmRef.Version == invalidWinMDVersion) continue; if (ver == null || asmRef.Version > ver) ver = asmRef.Version; } if (ver != null) asm.Version = ver; } return asm; } static readonly Version contractAsmVersion = new Version(4, 0, 0, 0); static readonly Version invalidWinMDVersion = new Version(255, 255, 255, 255); static readonly UTF8String mscorlibName = new UTF8String("mscorlib"); static UTF8String GetName(ClrAssembly clrAsm) { switch (clrAsm) { case ClrAssembly.Mscorlib: return clrAsmName_Mscorlib; case ClrAssembly.SystemNumericsVectors: return clrAsmName_SystemNumericsVectors; case ClrAssembly.SystemObjectModel: return clrAsmName_SystemObjectModel; case ClrAssembly.SystemRuntime: return clrAsmName_SystemRuntime; case ClrAssembly.SystemRuntimeInteropServicesWindowsRuntime: return clrAsmName_SystemRuntimeInteropServicesWindowsRuntime; case ClrAssembly.SystemRuntimeWindowsRuntime: return clrAsmName_SystemRuntimeWindowsRuntime; case ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml: return clrAsmName_SystemRuntimeWindowsRuntimeUIXaml; default: throw new InvalidOperationException(); } } static readonly UTF8String clrAsmName_Mscorlib = new UTF8String("mscorlib"); static readonly UTF8String clrAsmName_SystemNumericsVectors = new UTF8String("System.Numerics.Vectors"); static readonly UTF8String clrAsmName_SystemObjectModel = new UTF8String("System.ObjectModel"); static readonly UTF8String clrAsmName_SystemRuntime = new UTF8String("System.Runtime"); static readonly UTF8String clrAsmName_SystemRuntimeInteropServicesWindowsRuntime = new UTF8String("System.Runtime.InteropServices.WindowsRuntime"); static readonly UTF8String clrAsmName_SystemRuntimeWindowsRuntime = new UTF8String("System.Runtime.WindowsRuntime"); static readonly UTF8String clrAsmName_SystemRuntimeWindowsRuntimeUIXaml = new UTF8String("System.Runtime.WindowsRuntime.UI.Xaml"); static byte[] GetPublicKeyToken(ClrAssembly clrAsm) { switch (clrAsm) { case ClrAssembly.Mscorlib: return neutralPublicKey; case ClrAssembly.SystemNumericsVectors: return contractPublicKeyToken; case ClrAssembly.SystemObjectModel: return contractPublicKeyToken; case ClrAssembly.SystemRuntime: return contractPublicKeyToken; case ClrAssembly.SystemRuntimeInteropServicesWindowsRuntime: return contractPublicKeyToken; case ClrAssembly.SystemRuntimeWindowsRuntime: return neutralPublicKey; case ClrAssembly.SystemRuntimeWindowsRuntimeUIXaml: return neutralPublicKey; default: throw new InvalidOperationException(); } } static readonly byte[] contractPublicKeyToken = new byte[] { 0xB0, 0x3F, 0x5F, 0x7F, 0x11, 0xD5, 0x0A, 0x3A }; static readonly byte[] neutralPublicKey = new byte[] { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }; /// /// Converts WinMD type to a CLR type. Returns null /// if it's not a CLR compatible WinMD type. /// /// Owner module or null /// Type /// public static TypeRef ToCLR(ModuleDef module, TypeDef td) { bool isClrValueType; return ToCLR(module, td, out isClrValueType); } /// /// Converts WinMD type to a CLR type. Returns null /// if it's not a CLR compatible WinMD type. /// /// Owner module or null /// Type /// true if the returned type is a value type /// public static TypeRef ToCLR(ModuleDef module, TypeDef td, out bool isClrValueType) { isClrValueType = false; if (td == null || !td.IsWindowsRuntime) return null; var asm = td.DefinitionAssembly; if (asm == null || !asm.IsContentTypeWindowsRuntime) return null; ProjectedClass pc; if (!winMDToCLR.TryGetValue(new ClassName(td.Namespace, td.Name), out pc)) return null; isClrValueType = pc.ClrClass.IsValueType; return new TypeRefUser(module, pc.ClrClass.Namespace, pc.ClrClass.Name, CreateAssembly(module, pc.ContractAssembly)); } /// /// Converts WinMD type to a CLR type. Returns null /// if it's not a CLR compatible WinMD type. /// /// Owner module or null /// Type /// public static TypeRef ToCLR(ModuleDef module, TypeRef tr) { bool isClrValueType; return ToCLR(module, tr, out isClrValueType); } /// /// Converts WinMD type to a CLR type. Returns null /// if it's not a CLR compatible WinMD type. /// /// Owner module or null /// Type /// true if the returned type is a value type /// public static TypeRef ToCLR(ModuleDef module, TypeRef tr, out bool isClrValueType) { isClrValueType = false; if (tr == null) return null; var defAsm = tr.DefinitionAssembly; if (defAsm == null || !defAsm.IsContentTypeWindowsRuntime) return null; if (tr.DeclaringType != null) return null; ProjectedClass pc; if (!winMDToCLR.TryGetValue(new ClassName(tr.Namespace, tr.Name), out pc)) return null; isClrValueType = pc.ClrClass.IsValueType; return new TypeRefUser(module, pc.ClrClass.Namespace, pc.ClrClass.Name, CreateAssembly(module, pc.ContractAssembly)); } /// /// Converts WinMD type to a CLR type. Returns null /// if it's not a CLR compatible WinMD type. /// /// Owner module or null /// Type /// public static ExportedType ToCLR(ModuleDef module, ExportedType et) { if (et == null) return null; var defAsm = et.DefinitionAssembly; if (defAsm == null || !defAsm.IsContentTypeWindowsRuntime) return null; if (et.DeclaringType != null) return null; ProjectedClass pc; if (!winMDToCLR.TryGetValue(new ClassName(et.TypeNamespace, et.TypeName), out pc)) return null; return new ExportedTypeUser(module, 0, pc.ClrClass.Namespace, pc.ClrClass.Name, et.Attributes, CreateAssembly(module, pc.ContractAssembly)); } /// /// Converts WinMD type to a CLR type. Returns null /// if it's not a CLR compatible WinMD type. /// /// Owner module or null /// Type /// public static TypeSig ToCLR(ModuleDef module, TypeSig ts) { if (ts == null) return null; var et = ts.ElementType; if (et != ElementType.Class && et != ElementType.ValueType) return null; var tdr = ((ClassOrValueTypeSig)ts).TypeDefOrRef; TypeDef td; TypeRef tr, newTr; bool isClrValueType; if ((td = tdr as TypeDef) != null) { newTr = ToCLR(module, td, out isClrValueType); if (newTr == null) return null; } else if ((tr = tdr as TypeRef) != null) { newTr = ToCLR(module, tr, out isClrValueType); if (newTr == null) return null; } else return null; return isClrValueType ? (TypeSig)new ValueTypeSig(newTr) : new ClassSig(newTr); } /// /// Converts WinMD member reference to a CLR member reference. Returns /// null if it's not a CLR compatible WinMD member reference. /// /// Owner module or null /// Member reference /// public static MemberRef ToCLR(ModuleDef module, MemberRef mr) { // See WinMDAdapter::CheckIfMethodImplImplementsARedirectedInterface // in coreclr: md/winmd/adapter.cpp if (mr == null) return null; if (mr.Name != CloseName) return null; var msig = mr.MethodSig; if (msig == null) return null; var cl = mr.Class; IMemberRefParent newCl; TypeRef tr; TypeSpec ts; if ((tr = cl as TypeRef) != null) { var newTr = ToCLR(module, tr); if (newTr == null || !IsIDisposable(newTr)) return null; newCl = newTr; } else if ((ts = cl as TypeSpec) != null) { var gis = ts.TypeSig as GenericInstSig; if (gis == null || !(gis.GenericType is ClassSig)) return null; tr = gis.GenericType.TypeRef; if (tr == null) return null; bool isClrValueType; var newTr = ToCLR(module, tr, out isClrValueType); if (newTr == null || !IsIDisposable(newTr)) return null; newCl = new TypeSpecUser(new GenericInstSig(isClrValueType ? (ClassOrValueTypeSig)new ValueTypeSig(newTr) : new ClassSig(newTr), gis.GenericArguments)); } else return null; return new MemberRefUser(mr.Module, DisposeName, msig, newCl); } static readonly UTF8String CloseName = new UTF8String("Close"); static readonly UTF8String DisposeName = new UTF8String("Dispose"); static bool IsIDisposable(TypeRef tr) { return tr.Name == IDisposableName && tr.Namespace == IDisposableNamespace; } static readonly UTF8String IDisposableNamespace = new UTF8String("System"); static readonly UTF8String IDisposableName = new UTF8String("IDisposable"); /// /// Converts WinMD method to a CLR member reference. Returns /// null if it's not a CLR compatible WinMD method /// /// Owner module or null /// Method /// public static MemberRef ToCLR(ModuleDef module, MethodDef md) { if (md == null) return null; if (md.Name != CloseName) return null; var declType = md.DeclaringType; if (declType == null) return null; var tr = ToCLR(module, declType); if (tr == null || !IsIDisposable(tr)) return null; return new MemberRefUser(md.Module, DisposeName, md.MethodSig, tr); } } } dnlib-2.1_VS2010/src/DotNet/WinMDStatus.cs000066400000000000000000000006441325033663500200660ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet { /// /// WinMD status /// public enum WinMDStatus { /// /// This is not a WinMD file /// None, /// /// This is a pure WinMD file (not managed) /// Pure, /// /// This is a managed WinMD file (created by eg. winmdexp.exe) /// Managed, } } dnlib-2.1_VS2010/src/DotNet/Writer/000077500000000000000000000000001325033663500166255ustar00rootroot00000000000000dnlib-2.1_VS2010/src/DotNet/Writer/BinaryReaderChunk.cs000066400000000000000000000027231325033663500225200ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// A chunk /// public class BinaryReaderChunk : IChunk { FileOffset offset; RVA rva; readonly IBinaryReader data; readonly uint virtualSize; /// /// Gets the data /// public IBinaryReader Data { get { return data; } } /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Constructor /// /// The data public BinaryReaderChunk(IBinaryReader data) : this(data, (uint)data.Length) { } /// /// Constructor /// /// The data /// Virtual size of public BinaryReaderChunk(IBinaryReader data, uint virtualSize) { this.data = data; this.virtualSize = virtualSize; } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } /// public uint GetFileLength() { return (uint)data.Length; } /// public uint GetVirtualSize() { return virtualSize; } /// public void WriteTo(BinaryWriter writer) { data.Position = 0; data.WriteTo(writer); } } } dnlib-2.1_VS2010/src/DotNet/Writer/BlobHeap.cs000066400000000000000000000112031325033663500206250ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.IO; using dnlib.DotNet.MD; namespace dnlib.DotNet.Writer { /// /// #Blob heap /// public sealed class BlobHeap : HeapBase, IOffsetHeap { readonly Dictionary cachedDict = new Dictionary(ByteArrayEqualityComparer.Instance); readonly List cached = new List(); uint nextOffset = 1; byte[] originalData; Dictionary userRawData; /// public override string Name { get { return "#Blob"; } } /// /// Populates blobs from an existing (eg. to preserve /// blob offsets) /// /// The #Blob stream with the original content public void Populate(BlobStream blobStream) { if (isReadOnly) throw new ModuleWriterException("Trying to modify #Blob when it's read-only"); if (originalData != null) throw new InvalidOperationException("Can't call method twice"); if (nextOffset != 1) throw new InvalidOperationException("Add() has already been called"); if (blobStream == null || blobStream.ImageStreamLength == 0) return; using (var reader = blobStream.GetClonedImageStream()) { originalData = reader.ReadAllBytes(); nextOffset = (uint)originalData.Length; Populate(reader); } } void Populate(IImageStream reader) { reader.Position = 1; while (reader.Position < reader.Length) { uint offset = (uint)reader.Position; uint len; if (!reader.ReadCompressedUInt32(out len)) { if (offset == reader.Position) reader.Position++; continue; } if (len == 0 || reader.Position + len > reader.Length) continue; var data = reader.ReadBytes((int)len); if (!cachedDict.ContainsKey(data)) cachedDict[data] = offset; } } /// /// Adds data to the #Blob heap /// /// The data /// The offset of the data in the #Blob heap public uint Add(byte[] data) { if (isReadOnly) throw new ModuleWriterException("Trying to modify #Blob when it's read-only"); if (data == null || data.Length == 0) return 0; uint offset; if (cachedDict.TryGetValue(data, out offset)) return offset; return AddToCache(data); } /// /// Adds data to the #Blob heap, but does not re-use an existing position /// /// The data /// The offset of the data in the #Blob heap public uint Create(byte[] data) { if (isReadOnly) throw new ModuleWriterException("Trying to modify #Blob when it's read-only"); return AddToCache(data ?? new byte[0]); } uint AddToCache(byte[] data) { uint offset; cached.Add(data); cachedDict[data] = offset = nextOffset; nextOffset += (uint)GetRawDataSize(data); return offset; } /// public override uint GetRawLength() { return nextOffset; } /// protected override void WriteToImpl(BinaryWriter writer) { if (originalData != null) writer.Write(originalData); else writer.Write((byte)0); uint offset = originalData != null ? (uint)originalData.Length : 1; foreach (var data in cached) { int rawLen = GetRawDataSize(data); byte[] rawData; if (userRawData != null && userRawData.TryGetValue(offset, out rawData)) { if (rawData.Length != rawLen) throw new InvalidOperationException("Invalid length of raw data"); writer.Write(rawData); } else { writer.WriteCompressedUInt32((uint)data.Length); writer.Write(data); } offset += (uint)rawLen; } } /// public int GetRawDataSize(byte[] data) { return Utils.GetCompressedUInt32Length((uint)data.Length) + data.Length; } /// public void SetRawData(uint offset, byte[] rawData) { if (rawData == null) throw new ArgumentNullException("rawData"); if (userRawData == null) userRawData = new Dictionary(); userRawData[offset] = rawData; } /// public IEnumerable> GetAllRawData() { var memStream = new MemoryStream(); var writer = new BinaryWriter(memStream); uint offset = originalData != null ? (uint)originalData.Length : 1; foreach (var data in cached) { memStream.Position = 0; memStream.SetLength(0); writer.WriteCompressedUInt32((uint)data.Length); writer.Write(data); yield return new KeyValuePair(offset, memStream.ToArray()); offset += (uint)memStream.Length; } } } } dnlib-2.1_VS2010/src/DotNet/Writer/ByteArrayChunk.cs000066400000000000000000000034001325033663500220440ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Stores a byte array /// public sealed class ByteArrayChunk : IChunk { readonly byte[] array; FileOffset offset; RVA rva; /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Gets the data /// public byte[] Data { get { return array; } } /// /// Constructor /// /// The data. It will be owned by this instance and can't be modified by /// other code if this instance is inserted as a key in a dictionary (because /// return value will be different if you modify the array). If /// it's never inserted as a key in a dictionary, then the contents can be modified, /// but shouldn't be resized after has been called. public ByteArrayChunk(byte[] array) { this.array = array ?? new byte[0]; } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } /// public uint GetFileLength() { return (uint)array.Length; } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { writer.Write(array); } /// public override int GetHashCode() { return Utils.GetHashCode(array); } /// public override bool Equals(object obj) { var other = obj as ByteArrayChunk; return other != null && Utils.Equals(array, other.array); } } } dnlib-2.1_VS2010/src/DotNet/Writer/ChunkList.cs000066400000000000000000000026301325033663500210610ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; namespace dnlib.DotNet.Writer { /// /// Contains a list of s /// public class ChunkList : ChunkListBase where T : class, IChunk { /// /// Default constructor /// public ChunkList() { this.chunks = new List(); } /// /// Add a /// /// The chunk to add or null if none /// Chunk alignment public void Add(T chunk, uint alignment) { if (setOffsetCalled) throw new InvalidOperationException("SetOffset() has already been called"); if (chunk != null) chunks.Add(new Elem(chunk, alignment)); } /// /// Remove a /// /// The chunk to remove or null if none /// Alignment of the chunk, or null if the chunk cannot be removed. public uint? Remove(T chunk) { if (setOffsetCalled) throw new InvalidOperationException("SetOffset() has already been called"); if (chunk != null) { for (int i = 0; i < chunks.Count; i++) { if (chunks[i].chunk == chunk) { uint alignment = chunks[i].alignment; chunks.RemoveAt(i); return alignment; } } } return null; } } } dnlib-2.1_VS2010/src/DotNet/Writer/ChunkListBase.cs000066400000000000000000000063271325033663500216630ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.IO; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Base class of chunk list types /// /// Chunk type public abstract class ChunkListBase : IChunk where T : IChunk { /// All chunks protected List chunks; uint length; uint virtualSize; /// true if has been called protected bool setOffsetCalled; FileOffset offset; RVA rva; /// /// Helper struct /// protected struct Elem { /// Data public readonly T chunk; /// Alignment public readonly uint alignment; /// /// Constructor /// /// Chunk /// Alignment public Elem(T chunk, uint alignment) { this.chunk = chunk; this.alignment = alignment; } } /// /// Equality comparer for /// protected sealed class ElemEqualityComparer : IEqualityComparer { IEqualityComparer chunkComparer; /// /// Constructor /// /// Compares the chunk type public ElemEqualityComparer(IEqualityComparer chunkComparer) { this.chunkComparer = chunkComparer; } /// public bool Equals(Elem x, Elem y) { return x.alignment == y.alignment && chunkComparer.Equals(x.chunk, y.chunk); } /// public int GetHashCode(Elem obj) { return (int)obj.alignment + chunkComparer.GetHashCode(obj.chunk); } } /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// public virtual void SetOffset(FileOffset offset, RVA rva) { setOffsetCalled = true; this.offset = offset; this.rva = rva; length = 0; virtualSize = 0; foreach (var elem in chunks) { uint paddingF = (uint)offset.AlignUp(elem.alignment) - (uint)offset; uint paddingV = (uint)rva.AlignUp(elem.alignment) - (uint)rva; offset += paddingF; rva += paddingV; elem.chunk.SetOffset(offset, rva); if (elem.chunk.GetVirtualSize() == 0) { offset -= paddingF; rva -= paddingV; } else { uint chunkLenF = elem.chunk.GetFileLength(); uint chunkLenV = elem.chunk.GetVirtualSize(); offset += chunkLenF; rva += chunkLenV; length += paddingF + chunkLenF; virtualSize += paddingV + chunkLenV; } } } /// public uint GetFileLength() { return length; } /// public uint GetVirtualSize() { return virtualSize; } /// public void WriteTo(BinaryWriter writer) { FileOffset offset2 = offset; foreach (var elem in chunks) { if (elem.chunk.GetVirtualSize() == 0) continue; int paddingF = (int)offset2.AlignUp(elem.alignment) - (int)offset2; writer.WriteZeros(paddingF); elem.chunk.VerifyWriteTo(writer); offset2 += (uint)paddingF + elem.chunk.GetFileLength(); } } } } dnlib-2.1_VS2010/src/DotNet/Writer/CustomAttributeWriter.cs000066400000000000000000000532211325033663500235120ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; namespace dnlib.DotNet.Writer { /// /// Helps write custom attributes /// public interface ICustomAttributeWriterHelper : IWriterError, IFullNameCreatorHelper { } /// /// Writes s /// public struct CustomAttributeWriter : IDisposable { readonly ICustomAttributeWriterHelper helper; RecursionCounter recursionCounter; readonly MemoryStream outStream; readonly BinaryWriter writer; readonly bool disposeStream; GenericArguments genericArguments; /// /// Writes a custom attribute /// /// Helper class /// The custom attribute /// Custom attribute blob public static byte[] Write(ICustomAttributeWriterHelper helper, CustomAttribute ca) { using (var writer = new CustomAttributeWriter(helper)) { writer.Write(ca); return writer.GetResult(); } } internal static byte[] Write(ICustomAttributeWriterHelper helper, CustomAttribute ca, BinaryWriterContext context) { using (var writer = new CustomAttributeWriter(helper, context)) { writer.Write(ca); return writer.GetResult(); } } /// /// Writes custom attribute named arguments /// /// Helper class /// Named arguments /// The named args blob internal static byte[] Write(ICustomAttributeWriterHelper helper, IList namedArgs) { using (var writer = new CustomAttributeWriter(helper)) { writer.Write(namedArgs); return writer.GetResult(); } } internal static byte[] Write(ICustomAttributeWriterHelper helper, IList namedArgs, BinaryWriterContext context) { using (var writer = new CustomAttributeWriter(helper, context)) { writer.Write(namedArgs); return writer.GetResult(); } } CustomAttributeWriter(ICustomAttributeWriterHelper helper) { this.helper = helper; this.recursionCounter = new RecursionCounter(); this.outStream = new MemoryStream(); this.writer = new BinaryWriter(outStream); this.genericArguments = null; this.disposeStream = true; } CustomAttributeWriter(ICustomAttributeWriterHelper helper, BinaryWriterContext context) { this.helper = helper; this.recursionCounter = new RecursionCounter(); this.outStream = context.OutStream; this.writer = context.Writer; this.genericArguments = null; this.disposeStream = false; outStream.SetLength(0); outStream.Position = 0; } byte[] GetResult() { return outStream.ToArray(); } void Write(CustomAttribute ca) { if (ca == null) { helper.Error("The custom attribute is null"); return; } // Check whether it's raw first. If it is, we don't care whether the ctor is // invalid. Just use the raw data. if (ca.IsRawBlob) { if ((ca.ConstructorArguments != null && ca.ConstructorArguments.Count > 0) || (ca.NamedArguments != null && ca.NamedArguments.Count > 0)) helper.Error("Raw custom attribute contains arguments and/or named arguments"); writer.Write(ca.RawData); return; } if (ca.Constructor == null) { helper.Error("Custom attribute ctor is null"); return; } var methodSig = GetMethodSig(ca.Constructor); if (methodSig == null) { helper.Error("Custom attribute ctor's method signature is invalid"); return; } if (ca.ConstructorArguments.Count != methodSig.Params.Count) helper.Error("Custom attribute arguments count != method sig arguments count"); if (methodSig.ParamsAfterSentinel != null && methodSig.ParamsAfterSentinel.Count > 0) helper.Error("Custom attribute ctor has parameters after the sentinel"); if (ca.NamedArguments.Count > ushort.MaxValue) helper.Error("Custom attribute has too many named arguments"); // A generic custom attribute isn't allowed by most .NET languages (eg. C#) but // the CLR probably supports it. var mrCtor = ca.Constructor as MemberRef; if (mrCtor != null) { var owner = mrCtor.Class as TypeSpec; if (owner != null) { var gis = owner.TypeSig as GenericInstSig; if (gis != null) { genericArguments = new GenericArguments(); genericArguments.PushTypeArgs(gis.GenericArguments); } } } writer.Write((ushort)1); int numArgs = Math.Min(methodSig.Params.Count, ca.ConstructorArguments.Count); for (int i = 0; i < numArgs; i++) WriteValue(FixTypeSig(methodSig.Params[i]), ca.ConstructorArguments[i]); int numNamedArgs = Math.Min((int)ushort.MaxValue, ca.NamedArguments.Count); writer.Write((ushort)numNamedArgs); for (int i = 0; i < numNamedArgs; i++) Write(ca.NamedArguments[i]); } void Write(IList namedArgs) { if (namedArgs == null || namedArgs.Count > 0x1FFFFFFF) { helper.Error("Too many custom attribute named arguments"); namedArgs = new CANamedArgument[0]; } writer.WriteCompressedUInt32((uint)namedArgs.Count); for (int i = 0; i < namedArgs.Count; i++) Write(namedArgs[i]); } TypeSig FixTypeSig(TypeSig type) { return SubstituteGenericParameter(type.RemoveModifiers()).RemoveModifiers(); } TypeSig SubstituteGenericParameter(TypeSig type) { if (genericArguments == null) return type; return genericArguments.Resolve(type); } void WriteValue(TypeSig argType, CAArgument value) { if (argType == null || value.Type == null) { helper.Error("Custom attribute argument type is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } var arrayType = argType as SZArraySig; if (arrayType != null) { var argsArray = value.Value as IList; if (argsArray == null && value.Value != null) helper.Error("CAArgument.Value is not null or an array"); WriteArrayValue(arrayType, argsArray); } else WriteElem(argType, value); recursionCounter.Decrement(); } void WriteArrayValue(SZArraySig arrayType, IList args) { if (arrayType == null) { helper.Error("Custom attribute: Array type is null"); return; } if (args == null) writer.Write(uint.MaxValue); else { writer.Write((uint)args.Count); var arrayElementType = FixTypeSig(arrayType.Next); for (int i = 0; i < args.Count; i++) WriteValue(arrayElementType, args[i]); } } bool VerifyTypeAndValue(CAArgument value, ElementType etype) { if (!VerifyType(value.Type, etype)) { helper.Error("Custom attribute arg type != value.Type"); return false; } if (!VerifyValue(value.Value, etype)) { helper.Error("Custom attribute value.Value's type != value.Type"); return false; } return true; } bool VerifyTypeAndValue(CAArgument value, ElementType etype, Type valueType) { if (!VerifyType(value.Type, etype)) { helper.Error("Custom attribute arg type != value.Type"); return false; } return value.Value == null || value.Value.GetType() == valueType; } static bool VerifyType(TypeSig type, ElementType etype) { type = type.RemoveModifiers(); // Assume it's an enum if it's a ValueType return type != null && (etype == type.ElementType || type.ElementType == ElementType.ValueType); } static bool VerifyValue(object o, ElementType etype) { if (o == null) return false; switch (Type.GetTypeCode(o.GetType())) { case TypeCode.Boolean: return etype == ElementType.Boolean; case TypeCode.Char: return etype == ElementType.Char; case TypeCode.SByte: return etype == ElementType.I1; case TypeCode.Byte: return etype == ElementType.U1; case TypeCode.Int16: return etype == ElementType.I2; case TypeCode.UInt16: return etype == ElementType.U2; case TypeCode.Int32: return etype == ElementType.I4; case TypeCode.UInt32: return etype == ElementType.U4; case TypeCode.Int64: return etype == ElementType.I8; case TypeCode.UInt64: return etype == ElementType.U8; case TypeCode.Single: return etype == ElementType.R4; case TypeCode.Double: return etype == ElementType.R8; default: return false; } } static ulong ToUInt64(object o) { ulong result; ToUInt64(o, out result); return result; } static bool ToUInt64(object o, out ulong result) { if (o == null) { result = 0; return false; } switch (Type.GetTypeCode(o.GetType())) { case TypeCode.Boolean: result = (bool)o ? 1UL : 0UL; return true; case TypeCode.Char: result = (ushort)(char)o; return true; case TypeCode.SByte: result = (ulong)(sbyte)o; return true; case TypeCode.Byte: result = (byte)o; return true; case TypeCode.Int16: result = (ulong)(short)o; return true; case TypeCode.UInt16: result = (ushort)o; return true; case TypeCode.Int32: result = (ulong)(int)o; return true; case TypeCode.UInt32: result = (uint)o; return true; case TypeCode.Int64: result = (ulong)(long)o; return true; case TypeCode.UInt64: result = (ulong)o; return true; case TypeCode.Single: result = (ulong)(float)o; return true; case TypeCode.Double: result = (ulong)(double)o; return true; } result = 0; return false; } static double ToDouble(object o) { double result; ToDouble(o, out result); return result; } static bool ToDouble(object o, out double result) { if (o == null) { result = double.NaN; return false; } switch (Type.GetTypeCode(o.GetType())) { case TypeCode.Boolean: result = (bool)o ? 1 : 0; return true; case TypeCode.Char: result = (ushort)(char)o; return true; case TypeCode.SByte: result = (sbyte)o; return true; case TypeCode.Byte: result = (byte)o; return true; case TypeCode.Int16: result = (short)o; return true; case TypeCode.UInt16: result = (ushort)o; return true; case TypeCode.Int32: result = (int)o; return true; case TypeCode.UInt32: result = (uint)o; return true; case TypeCode.Int64: result = (long)o; return true; case TypeCode.UInt64: result = (ulong)o; return true; case TypeCode.Single: result = (float)o; return true; case TypeCode.Double: result = (double)o; return true; } result = double.NaN; return false; } /// /// Write a value /// /// The ctor arg type, field type, or property type /// The value to write void WriteElem(TypeSig argType, CAArgument value) { if (argType == null) { helper.Error("Custom attribute: Arg type is null"); argType = value.Type; if (argType == null) return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } TypeSig underlyingType; ITypeDefOrRef tdr; switch (argType.ElementType) { case ElementType.Boolean: if (!VerifyTypeAndValue(value, ElementType.Boolean)) writer.Write(ToUInt64(value.Value) != 0); else writer.Write((bool)value.Value); break; case ElementType.Char: if (!VerifyTypeAndValue(value, ElementType.Char)) writer.Write((ushort)ToUInt64(value.Value)); else writer.Write((ushort)(char)value.Value); break; case ElementType.I1: if (!VerifyTypeAndValue(value, ElementType.I1)) writer.Write((sbyte)ToUInt64(value.Value)); else writer.Write((sbyte)value.Value); break; case ElementType.U1: if (!VerifyTypeAndValue(value, ElementType.U1)) writer.Write((byte)ToUInt64(value.Value)); else writer.Write((byte)value.Value); break; case ElementType.I2: if (!VerifyTypeAndValue(value, ElementType.I2)) writer.Write((short)ToUInt64(value.Value)); else writer.Write((short)value.Value); break; case ElementType.U2: if (!VerifyTypeAndValue(value, ElementType.U2)) writer.Write((ushort)ToUInt64(value.Value)); else writer.Write((ushort)value.Value); break; case ElementType.I4: if (!VerifyTypeAndValue(value, ElementType.I4)) writer.Write((int)ToUInt64(value.Value)); else writer.Write((int)value.Value); break; case ElementType.U4: if (!VerifyTypeAndValue(value, ElementType.U4)) writer.Write((uint)ToUInt64(value.Value)); else writer.Write((uint)value.Value); break; case ElementType.I8: if (!VerifyTypeAndValue(value, ElementType.I8)) writer.Write((long)ToUInt64(value.Value)); else writer.Write((long)value.Value); break; case ElementType.U8: if (!VerifyTypeAndValue(value, ElementType.U8)) writer.Write(ToUInt64(value.Value)); else writer.Write((ulong)value.Value); break; case ElementType.R4: if (!VerifyTypeAndValue(value, ElementType.R4)) writer.Write((float)ToDouble(value.Value)); else writer.Write((float)value.Value); break; case ElementType.R8: if (!VerifyTypeAndValue(value, ElementType.R8)) writer.Write(ToDouble(value.Value)); else writer.Write((double)value.Value); break; case ElementType.String: if (VerifyTypeAndValue(value, ElementType.String, typeof(UTF8String))) WriteUTF8String((UTF8String)value.Value); else if (VerifyTypeAndValue(value, ElementType.String, typeof(string))) WriteUTF8String((string)value.Value); else WriteUTF8String(UTF8String.Empty); break; case ElementType.ValueType: tdr = ((TypeDefOrRefSig)argType).TypeDefOrRef; underlyingType = GetEnumUnderlyingType(argType); if (underlyingType != null) WriteElem(underlyingType, value); else if (tdr is TypeRef && TryWriteEnumUnderlyingTypeValue(value.Value)) { // No error. Assume it's an enum that couldn't be resolved. } else helper.Error("Custom attribute value is not an enum"); break; case ElementType.Class: tdr = ((TypeDefOrRefSig)argType).TypeDefOrRef; if (CheckCorLibType(argType, "Type")) { if (CheckCorLibType(value.Type, "Type")) { var ts = value.Value as TypeSig; if (ts != null) WriteType(ts); else if (value.Value == null) WriteUTF8String(null); else { helper.Error("Custom attribute value is not a type"); WriteUTF8String(UTF8String.Empty); } } else { helper.Error("Custom attribute value type is not System.Type"); WriteUTF8String(UTF8String.Empty); } break; } else if (tdr is TypeRef && TryWriteEnumUnderlyingTypeValue(value.Value)) { // No error. Assume it's an enum that couldn't be resolved. break; } goto default; case ElementType.SZArray: WriteValue(argType, value); break; case ElementType.Object: WriteFieldOrPropType(value.Type); WriteElem(value.Type, value); break; case ElementType.End: case ElementType.Void: case ElementType.Ptr: case ElementType.ByRef: case ElementType.Var: case ElementType.Array: case ElementType.GenericInst: case ElementType.TypedByRef: case ElementType.ValueArray: case ElementType.I: case ElementType.U: case ElementType.R: case ElementType.FnPtr: case ElementType.MVar: case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Internal: case ElementType.Module: case ElementType.Sentinel: case ElementType.Pinned: default: helper.Error("Invalid or unsupported element type in custom attribute"); break; } recursionCounter.Decrement(); } bool TryWriteEnumUnderlyingTypeValue(object o) { if (o == null) return false; switch (Type.GetTypeCode(o.GetType())) { case TypeCode.Boolean: writer.Write((bool)o); break; case TypeCode.Char: writer.Write((ushort)(char)o); break; case TypeCode.SByte: writer.Write((sbyte)o); break; case TypeCode.Byte: writer.Write((byte)o); break; case TypeCode.Int16: writer.Write((short)o); break; case TypeCode.UInt16: writer.Write((ushort)o); break; case TypeCode.Int32: writer.Write((int)o); break; case TypeCode.UInt32: writer.Write((uint)o); break; case TypeCode.Int64: writer.Write((long)o); break; case TypeCode.UInt64: writer.Write((ulong)o); break; default: return false; } return true; } /// /// Gets the enum's underlying type /// /// An enum type /// The underlying type or null if we couldn't resolve the type ref static TypeSig GetEnumUnderlyingType(TypeSig type) { var td = GetEnumTypeDef(type); if (td == null) return null; return td.GetEnumUnderlyingType().RemoveModifiers(); } static TypeDef GetEnumTypeDef(TypeSig type) { if (type == null) return null; var td = GetTypeDef(type); if (td == null) return null; if (!td.IsEnum) return null; return td; } /// /// Converts to a , possibly resolving /// a /// /// The type /// A or null if we couldn't resolve the /// or if is a type spec static TypeDef GetTypeDef(TypeSig type) { var tdr = type as TypeDefOrRefSig; if (tdr != null) { var td = tdr.TypeDef; if (td != null) return td; var tr = tdr.TypeRef; if (tr != null) return tr.Resolve(); } return null; } void Write(CANamedArgument namedArg) { if (namedArg == null) { helper.Error("Custom attribute named arg is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } if (namedArg.IsProperty) writer.Write((byte)SerializationType.Property); else writer.Write((byte)SerializationType.Field); WriteFieldOrPropType(namedArg.Type); WriteUTF8String(namedArg.Name); WriteValue(namedArg.Type, namedArg.Argument); recursionCounter.Decrement(); } void WriteFieldOrPropType(TypeSig type) { type = type.RemoveModifiers(); if (type == null) { helper.Error("Custom attribute: Field/property type is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } ITypeDefOrRef tdr; switch (type.ElementType) { case ElementType.Boolean: writer.Write((byte)SerializationType.Boolean); break; case ElementType.Char: writer.Write((byte)SerializationType.Char); break; case ElementType.I1: writer.Write((byte)SerializationType.I1); break; case ElementType.U1: writer.Write((byte)SerializationType.U1); break; case ElementType.I2: writer.Write((byte)SerializationType.I2); break; case ElementType.U2: writer.Write((byte)SerializationType.U2); break; case ElementType.I4: writer.Write((byte)SerializationType.I4); break; case ElementType.U4: writer.Write((byte)SerializationType.U4); break; case ElementType.I8: writer.Write((byte)SerializationType.I8); break; case ElementType.U8: writer.Write((byte)SerializationType.U8); break; case ElementType.R4: writer.Write((byte)SerializationType.R4); break; case ElementType.R8: writer.Write((byte)SerializationType.R8); break; case ElementType.String: writer.Write((byte)SerializationType.String); break; case ElementType.Object: writer.Write((byte)SerializationType.TaggedObject); break; case ElementType.SZArray: writer.Write((byte)SerializationType.SZArray); WriteFieldOrPropType(type.Next); break; case ElementType.Class: tdr = ((TypeDefOrRefSig)type).TypeDefOrRef; if (CheckCorLibType(type, "Type")) writer.Write((byte)SerializationType.Type); else if (tdr is TypeRef) { // Could be an enum TypeRef that couldn't be resolved, so the code // assumed it's a class and created a ClassSig. writer.Write((byte)SerializationType.Enum); WriteType(tdr); } else goto default; break; case ElementType.ValueType: tdr = ((TypeDefOrRefSig)type).TypeDefOrRef; var enumType = GetEnumTypeDef(type); // If TypeRef => assume it's an enum that couldn't be resolved if (enumType != null || tdr is TypeRef) { writer.Write((byte)SerializationType.Enum); WriteType(tdr); } else { helper.Error("Custom attribute type doesn't seem to be an enum."); writer.Write((byte)SerializationType.Enum); WriteType(tdr); } break; default: helper.Error("Custom attribute: Invalid type"); writer.Write((byte)0xFF); break; } recursionCounter.Decrement(); } void WriteType(IType type) { if (type == null) { helper.Error("Custom attribute: Type is null"); WriteUTF8String(UTF8String.Empty); } else WriteUTF8String(FullNameCreator.AssemblyQualifiedName(type, helper)); } static bool CheckCorLibType(TypeSig ts, string name) { var tdrs = ts as TypeDefOrRefSig; if (tdrs == null) return false; return CheckCorLibType(tdrs.TypeDefOrRef, name); } static bool CheckCorLibType(ITypeDefOrRef tdr, string name) { if (tdr == null) return false; if (!tdr.DefinitionAssembly.IsCorLib()) return false; if (tdr is TypeSpec) return false; return tdr.TypeName == name && tdr.Namespace == "System"; } static MethodSig GetMethodSig(ICustomAttributeType ctor) { return ctor == null ? null : ctor.MethodSig; } void WriteUTF8String(UTF8String s) { if ((object)s == null || s.Data == null) writer.Write((byte)0xFF); else { writer.WriteCompressedUInt32((uint)s.Data.Length); writer.Write(s.Data); } } /// public void Dispose() { if (!disposeStream) return; if (outStream != null) outStream.Dispose(); if (writer != null) ((IDisposable)writer).Dispose(); } } } dnlib-2.1_VS2010/src/DotNet/Writer/DebugDirectory.cs000066400000000000000000000061641325033663500220760ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.IO; using dnlib.DotNet.Pdb; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Debug directory entry /// public sealed class DebugDirectoryEntry { /// /// Gets the header /// public IMAGE_DEBUG_DIRECTORY DebugDirectory; /// /// Gets the data /// public readonly IChunk Chunk; /// /// Constructor /// /// Data public DebugDirectoryEntry(IChunk chunk) { Chunk = chunk; } } /// /// Debug directory chunk /// public sealed class DebugDirectory : IChunk { /// Default debug directory alignment public const uint DEFAULT_DEBUGDIRECTORY_ALIGNMENT = 4; const int HEADER_SIZE = 28; FileOffset offset; RVA rva; uint length; readonly List entries; /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Constructor /// public DebugDirectory() { entries = new List(); } /// /// Adds data /// /// Data /// public DebugDirectoryEntry Add(byte[] data) { return Add(new ByteArrayChunk(data)); } /// /// Adds data /// /// Data /// public DebugDirectoryEntry Add(IChunk chunk) { var entry = new DebugDirectoryEntry(chunk); entries.Add(entry); return entry; } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; length = HEADER_SIZE * (uint)entries.Count; foreach (var entry in entries) { length = Utils.AlignUp(length, DEFAULT_DEBUGDIRECTORY_ALIGNMENT); entry.Chunk.SetOffset(offset + length, rva + length); length += entry.Chunk.GetFileLength(); } } /// public uint GetFileLength() { return length; } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { uint offset = 0; foreach (var entry in entries) { writer.Write(entry.DebugDirectory.Characteristics); writer.Write(entry.DebugDirectory.TimeDateStamp); writer.Write(entry.DebugDirectory.MajorVersion); writer.Write(entry.DebugDirectory.MinorVersion); writer.Write((uint)entry.DebugDirectory.Type); writer.Write(entry.Chunk.GetFileLength()); writer.Write((uint)entry.Chunk.RVA); writer.Write((uint)entry.Chunk.FileOffset); offset += HEADER_SIZE; } foreach (var entry in entries) { WriteAlign(writer, ref offset); entry.Chunk.VerifyWriteTo(writer); offset += entry.Chunk.GetFileLength(); } } static void WriteAlign(BinaryWriter writer, ref uint offs) { uint align = Utils.AlignUp(offs, DEFAULT_DEBUGDIRECTORY_ALIGNMENT) - offs; offs += align; writer.WriteZeros((int)align); } } } dnlib-2.1_VS2010/src/DotNet/Writer/DeclSecurityWriter.cs000066400000000000000000000063321325033663500227540ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.IO; using System.Text; namespace dnlib.DotNet.Writer { /// /// Writes DeclSecurity blobs /// public struct DeclSecurityWriter : ICustomAttributeWriterHelper { readonly ModuleDef module; readonly IWriterError helper; readonly BinaryWriterContext context; /// /// Creates a DeclSecurity blob from /// /// Owner module /// List of s /// Helps this class /// A DeclSecurity blob public static byte[] Write(ModuleDef module, IList secAttrs, IWriterError helper) { return new DeclSecurityWriter(module, helper, null).Write(secAttrs); } internal static byte[] Write(ModuleDef module, IList secAttrs, IWriterError helper, BinaryWriterContext context) { return new DeclSecurityWriter(module, helper, context).Write(secAttrs); } DeclSecurityWriter(ModuleDef module, IWriterError helper, BinaryWriterContext context) { this.module = module; this.helper = helper; this.context = context; } byte[] Write(IList secAttrs) { if (secAttrs == null) secAttrs = new SecurityAttribute[0]; var xml = DeclSecurity.GetNet1xXmlStringInternal(secAttrs); if (xml != null) return WriteFormat1(xml); return WriteFormat2(secAttrs); } byte[] WriteFormat1(string xml) { return Encoding.Unicode.GetBytes(xml); } byte[] WriteFormat2(IList secAttrs) { using (var stream = new MemoryStream()) using (var writer = new BinaryWriter(stream)) { writer.Write((byte)'.'); WriteCompressedUInt32(writer, (uint)secAttrs.Count); foreach (var sa in secAttrs) { if (sa == null) { helper.Error("SecurityAttribute is null"); Write(writer, UTF8String.Empty); WriteCompressedUInt32(writer, 1); WriteCompressedUInt32(writer, 0); continue; } var attrType = sa.AttributeType; string fqn; if (attrType == null) { helper.Error("SecurityAttribute attribute type is null"); fqn = string.Empty; } else fqn = attrType.AssemblyQualifiedName; Write(writer, fqn); var namedArgsBlob = context == null ? CustomAttributeWriter.Write(this, sa.NamedArguments) : CustomAttributeWriter.Write(this, sa.NamedArguments, context); if (namedArgsBlob.Length > 0x1FFFFFFF) { helper.Error("Named arguments blob size doesn't fit in 29 bits"); namedArgsBlob = new byte[0]; } WriteCompressedUInt32(writer, (uint)namedArgsBlob.Length); writer.Write(namedArgsBlob); } return stream.ToArray(); } } uint WriteCompressedUInt32(BinaryWriter writer, uint value) { return writer.WriteCompressedUInt32(helper, value); } void Write(BinaryWriter writer, UTF8String s) { writer.Write(helper, s); } void IWriterError.Error(string message) { helper.Error(message); } bool IFullNameCreatorHelper.MustUseAssemblyName(IType type) { return FullNameCreator.MustUseAssemblyName(module, type); } } } dnlib-2.1_VS2010/src/DotNet/Writer/Extensions.cs000066400000000000000000000010431325033663500213110ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; namespace dnlib.DotNet.Writer { /// /// Extension methods /// public static partial class Extensions { /// /// Write zeros /// /// this /// Number of zeros public static void WriteZeros(this BinaryWriter writer, int count) { if (count <= 0x20) { for (int i = 0; i < count; i++) writer.Write((byte)0); } else writer.Write(new byte[count]); } } } dnlib-2.1_VS2010/src/DotNet/Writer/GuidHeap.cs000066400000000000000000000037471325033663500206550ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; namespace dnlib.DotNet.Writer { /// /// #GUID heap /// public sealed class GuidHeap : HeapBase, IOffsetHeap { readonly Dictionary guids = new Dictionary(); Dictionary userRawData; /// public override string Name { get { return "#GUID"; } } /// /// Adds a guid to the #GUID heap /// /// The guid /// The index of the guid in the #GUID heap public uint Add(Guid? guid) { if (isReadOnly) throw new ModuleWriterException("Trying to modify #GUID when it's read-only"); if (guid == null) return 0; uint index; if (guids.TryGetValue(guid.Value, out index)) return index; index = (uint)guids.Count + 1; guids.Add(guid.Value, index); return index; } /// public override uint GetRawLength() { return (uint)guids.Count * 16; } /// protected override void WriteToImpl(BinaryWriter writer) { uint offset = 0; foreach (var kv in guids) { byte[] rawData; if (userRawData == null || !userRawData.TryGetValue(offset, out rawData)) rawData = kv.Key.ToByteArray(); writer.Write(rawData); offset += 16; } } /// public int GetRawDataSize(Guid data) { return 16; } /// public void SetRawData(uint offset, byte[] rawData) { if (rawData == null || rawData.Length != 16) throw new ArgumentException("Invalid size of GUID raw data"); if (userRawData == null) userRawData = new Dictionary(); userRawData[offset] = rawData; } /// public IEnumerable> GetAllRawData() { uint offset = 0; foreach (var kv in guids) { yield return new KeyValuePair(offset, kv.Key.ToByteArray()); offset += 16; } } } } dnlib-2.1_VS2010/src/DotNet/Writer/HeapBase.cs000066400000000000000000000036201325033663500206250ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Base class of most heaps /// public abstract class HeapBase : IHeap { internal const uint ALIGNMENT = 4; FileOffset offset; RVA rva; /// /// true if has been called /// protected bool isReadOnly; /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// public abstract string Name { get; } /// public bool IsEmpty { get { return GetRawLength() <= 1; } } /// /// true if offsets require 4 bytes instead of 2 bytes. /// public bool IsBig { get { return GetFileLength() > 0xFFFF; } } /// public void SetReadOnly() { isReadOnly = true; } /// public virtual void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } /// public uint GetFileLength() { return Utils.AlignUp(GetRawLength(), ALIGNMENT); } /// public uint GetVirtualSize() { return GetFileLength(); } /// /// Gets the raw length of the heap /// /// Raw length of the heap public abstract uint GetRawLength(); /// public void WriteTo(BinaryWriter writer) { WriteToImpl(writer); writer.WriteZeros((int)(Utils.AlignUp(GetRawLength(), ALIGNMENT) - GetRawLength())); } /// /// Writes all data to at its current location. /// /// Destination protected abstract void WriteToImpl(BinaryWriter writer); /// public override string ToString() { return Name; } } } dnlib-2.1_VS2010/src/DotNet/Writer/HotHeap.cs000066400000000000000000000163301325033663500205070ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.DotNet.MD; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// The hot metadata heap: #!. MS' CLR 2.0+ can read this heap. It's used by native /// images (NGEN'd) only, but if you patch the CLR, you can use it with normal non-NGEN'd /// images as well. /// It's only used by the CLR when the compressed heap (#~) is present, not when /// the ENC heap (#-) is present. /// abstract class HotHeap : HeapBase { const uint HOT_HEAP_MAGIC = 0x484F4E44; // "HOND" const int MAX_TABLES = (int)Table.GenericParamConstraint + 1; const uint HOT_HEAP_DIR_SIZE = 4 + MAX_TABLES * 4; const uint HH_ALIGNMENT = 4; protected readonly MetaData metadata; uint totalLength; readonly HotTable[] headers = new HotTable[MAX_TABLES]; readonly List hotPools = new List(); /// /// Gets the hot heap version /// public abstract HotHeapVersion HotHeapVersion { get; } /// public override string Name { get { return "#!"; } } /// /// Constructor /// /// Metadata owner protected HotHeap(MetaData metadata) { this.metadata = metadata; } /// /// Creates a instance /// /// The MD table public abstract HotTable CreateHotTable(IMDTable mdTable); /// /// Creates a instance /// /// Pool type public abstract HotPool CreateHotPool(HeapType heapType); /// /// Creates a hot heap instance /// /// Metadata owner /// Target module public static HotHeap Create(MetaData metadata, ModuleDef module) { return Create(metadata, GetHotHeapVersion(module)); } /// /// Creates a hot heap instance /// /// Metadata owner /// Hot heap version public static HotHeap Create(MetaData metadata, HotHeapVersion version) { switch (version) { case HotHeapVersion.CLR20: return new HotHeap20(metadata); case HotHeapVersion.CLR40: return new HotHeap40(metadata); default: throw new ArgumentException("Invalid version"); } } /// /// Returns the correct hot heap version that should be used /// /// Target module public static HotHeapVersion GetHotHeapVersion(ModuleDef module) { if (module.IsClr20) return HotHeapVersion.CLR20; return HotHeapVersion.CLR40; } /// /// Adds a hot table /// /// The hot table public void Add(HotTable hotTable) { var table = hotTable.Table; if ((uint)table >= (uint)headers.Length) throw new ArgumentException("Invalid table type"); headers[(int)table] = hotTable; } /// /// Adds a hot pool /// /// The hot pool public void Add(HotPool hotPool) { hotPools.Add(hotPool); } /// public override void SetOffset(FileOffset offset, RVA rva) { base.SetOffset(offset, rva); uint startOffs = (uint)offset; offset += HOT_HEAP_DIR_SIZE; rva += HOT_HEAP_DIR_SIZE; foreach (var header in headers) { if (header == null) continue; header.SetOffset(offset, rva); uint len = header.GetFileLength(); offset += len; rva += len; Align(ref offset, ref rva); } foreach (var hotPool in hotPools) { Align(ref offset, ref rva); hotPool.SetOffset(offset, rva); uint len = hotPool.GetFileLength(); offset += len; rva += len; } Align(ref offset, ref rva); offset += hotPools.Count * 8; rva += (uint)hotPools.Count * 8; offset += 8; rva += 8; totalLength = (uint)offset - startOffs; } static void Align(ref FileOffset offset, ref RVA rva) { offset = offset.AlignUp(HH_ALIGNMENT); rva = rva.AlignUp(HH_ALIGNMENT); } /// public override uint GetRawLength() { return totalLength; } /// protected override void WriteToImpl(BinaryWriter writer) { // The CLR doesn't verify this magic value writer.Write(HOT_HEAP_MAGIC); uint offs = HOT_HEAP_DIR_SIZE; foreach (var header in headers) { if (header == null) writer.Write(0); else { writer.Write(offs); // any alignment, all bits are used offs += header.GetFileLength(); offs = Utils.AlignUp(offs, HH_ALIGNMENT); } } offs = HOT_HEAP_DIR_SIZE; foreach (var header in headers) { if (header == null) continue; header.VerifyWriteTo(writer); offs += header.GetFileLength(); WriteAlign(writer, ref offs); } var hotPoolOffset = new List(); foreach (var hotPool in hotPools) { WriteAlign(writer, ref offs); hotPoolOffset.Add(writer.BaseStream.Position); hotPool.VerifyWriteTo(writer); offs += hotPool.GetFileLength(); } WriteAlign(writer, ref offs); long poolDBOffs = writer.BaseStream.Position; for (int i = 0; i < hotPools.Count; i++) { var hotPool = hotPools[i]; writer.Write((uint)hotPool.HeapType); // CLR 2.0: low 2 bits are ignored // CLR 4.0: any alignment, all bits are used writer.Write((uint)(poolDBOffs - hotPoolOffset[i] - hotPool.HeaderOffset)); } offs += (uint)hotPools.Count * 8; long hotMDDirOffs = writer.BaseStream.Position; // any alignment writer.Write((uint)(offs - HOT_HEAP_DIR_SIZE)); // CLR 2.0: low 2 bits are ignored // CLR 4.0: any alignment, all bits are used writer.Write((uint)(hotMDDirOffs - poolDBOffs)); } static void WriteAlign(BinaryWriter writer, ref uint offs) { uint align = Utils.AlignUp(offs, HH_ALIGNMENT) - offs; offs += align; writer.WriteZeros((int)align); } } /// /// CLR 2.0 (.NET 2.0 - 3.5) hot heap (#!) /// sealed class HotHeap20 : HotHeap { /// public override HotHeapVersion HotHeapVersion { get { return HotHeapVersion.CLR20; } } /// /// Constructor /// /// Metadata owner public HotHeap20(MetaData metadata) : base(metadata) { } /// public override HotTable CreateHotTable(IMDTable mdTable) { return new HotTable20(metadata, mdTable); } /// public override HotPool CreateHotPool(HeapType heapType) { return new HotPool20(heapType); } } /// /// CLR 4.0 (.NET 4.0 - 4.5) hot heap (#!) /// sealed class HotHeap40 : HotHeap { /// public override HotHeapVersion HotHeapVersion { get { return HotHeapVersion.CLR40; } } /// /// Constructor /// /// Metadata owner public HotHeap40(MetaData metadata) : base(metadata) { } /// public override HotTable CreateHotTable(IMDTable mdTable) { return new HotTable40(metadata, mdTable); } /// public override HotPool CreateHotPool(HeapType heapType) { return new HotPool40(heapType); } } } dnlib-2.1_VS2010/src/DotNet/Writer/HotPool.cs000066400000000000000000000241671325033663500205520ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.DotNet.MD; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Hot pool /// abstract class HotPool : IChunk { internal const uint HP_ALIGNMENT = 4; FileOffset offset; RVA rva; readonly HeapType heapType; Dictionary allData; internal DataInfo[] dataList; int[] sortedIndexes; internal uint dataOffset; internal uint indexesOffset; internal uint ridsOffset; internal uint headerOffset; uint totalLength; bool indexesIsSorted; internal class DataInfo { public readonly uint HeapOffset; public uint PoolOffset; public readonly byte[] Data; public DataInfo(uint heapOffset, byte[] data) { this.HeapOffset = heapOffset; this.Data = data; } } /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Gets the offset of the data relative to the start of this chunk. This is valid only /// after has been called. /// public uint DataOffset { get { return dataOffset; } } /// /// Gets the offset of the indexes relative to the start of this chunk. This is valid only /// after has been called. /// public uint IndexesOffset { get { return indexesOffset; } } /// /// Gets the offset of the rids relative to the start of this chunk. This is valid only /// after has been called. /// public uint RidsOffset { get { return ridsOffset; } } /// /// Gets the offset of the header relative to the start of this chunk. This is valid only /// after has been called. /// public uint HeaderOffset { get { return headerOffset; } } /// /// Gets the pool type /// public HeapType HeapType { get { return heapType; } } /// /// Constructor /// /// Pool type internal HotPool(HeapType heapType) { this.heapType = heapType; this.allData = new Dictionary(); } /// /// Adds raw data /// /// Offset of data in the original heap. If it's the #GUID, this /// should be (index - 1) * 16. /// public void Add(uint offset, byte[] rawData) { if (dataList != null) throw new InvalidOperationException("Can't Add() after CreateData() has been called"); allData[offset] = rawData; } /// /// Creates if it hasn't been created yet /// void CreateData() { if (dataList != null) return; dataList = new DataInfo[allData.Count]; int i = 0; foreach (var kv in allData) dataList[i++] = new DataInfo(kv.Key, kv.Value); // Make sure it's sorted by heap offset Array.Sort(dataList, (a, b) => a.HeapOffset.CompareTo(b.HeapOffset)); sortedIndexes = new int[allData.Count]; for (i = 0; i < sortedIndexes.Length; i++) sortedIndexes[i] = i; allData = null; indexesIsSorted = false; } /// /// Creates the data and sorts it according to the original data's heap offsets /// public void SortData() { CreateData(); Array.Sort(sortedIndexes, (a, b) => a.CompareTo(b)); indexesIsSorted = true; } /// /// Creates the data and shuffles it /// public void ShuffleData() { ShuffleData(new Random()); } /// /// Creates the data and shuffles it /// /// Random number generator instance that should be used public void ShuffleData(Random rand) { CreateData(); int start = 0, len = sortedIndexes.Length; GetValidShuffleRange(ref start, ref len); Shuffle(rand, sortedIndexes, start, len); indexesIsSorted = true; } /// /// Returns the range that can be shuffled /// /// Start index /// Length internal virtual void GetValidShuffleRange(ref int start, ref int length) { } static void Shuffle(Random rand, IList list, int start, int count) { if (list == null || count <= 1) return; // Fisher-Yates algo, see http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle for (int i = count - 1; i > 0; i--) { int j = rand.Next(i + 1); T tmp = list[start + i]; list[start + i] = list[start + j]; list[start + j] = tmp; } } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; CreateData(); totalLength = SetOffsetImpl(); } /// /// Initializes all offsets /// /// Total size of data internal abstract uint SetOffsetImpl(); internal uint GetDataSize() { uint size = 0; foreach (var data in dataList) size += (uint)data.Data.Length; return size; } /// public uint GetFileLength() { return totalLength; } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { // Sort it unless it's already been sorted. Don't want random order // unless the user wants it. if (!indexesIsSorted) SortData(); WriteToImpl(writer); dataList = null; sortedIndexes = null; } /// /// Writes all data /// internal abstract void WriteToImpl(BinaryWriter writer); internal DataInfo[] GetPoolDataOrder() { var dataList2 = (DataInfo[])dataList.Clone(); Array.Sort(sortedIndexes, dataList2); uint offset = 0; foreach (var info in dataList2) { info.PoolOffset = offset; offset += (uint)info.Data.Length; } return dataList2; } } /// /// CLR 2.0 (.NET 2.0 - 3.5) hot pool writer /// sealed class HotPool20 : HotPool { /// /// Constructor /// /// Pool type public HotPool20(HeapType heapType) : base(heapType) { } /// internal override void GetValidShuffleRange(ref int start, ref int length) { // First one must always be first start++; length--; } /// internal override uint SetOffsetImpl() { uint offs = 0; // data can be anywhere except where rids can be offs = Utils.AlignUp(offs, HP_ALIGNMENT); dataOffset = offs; offs += GetDataSize(); // indexes can be anywhere except where rids can be offs = Utils.AlignUp(offs, HP_ALIGNMENT); indexesOffset = offs; offs += ((uint)dataList.Length - 1) * 4; // rids must be right before the header offs = Utils.AlignUp(offs, HP_ALIGNMENT); ridsOffset = offs; offs += (uint)dataList.Length * 4; offs = Utils.AlignUp(offs, HP_ALIGNMENT); headerOffset = offs; offs += 3 * 4; return offs; } /// internal override void WriteToImpl(BinaryWriter writer) { uint offs = 0; long startPos = writer.BaseStream.Position; var dataList2 = GetPoolDataOrder(); // Write data writer.WriteZeros((int)(dataOffset - offs)); foreach (var kv in dataList2) writer.Write(kv.Data); offs = (uint)(writer.BaseStream.Position - startPos); // Write indexes (hot pool offsets) writer.WriteZeros((int)(indexesOffset - offs)); if (dataList.Length > 1) { for (int i = 1; i < dataList.Length; i++) writer.Write(dataList[i].PoolOffset); } offs = (uint)(writer.BaseStream.Position - startPos); // Write rids (heap offsets) writer.WriteZeros((int)(ridsOffset - offs)); foreach (var kv in dataList) writer.Write(kv.HeapOffset); offs = (uint)(writer.BaseStream.Position - startPos); // Write header writer.WriteZeros((int)(headerOffset - offs)); writer.Write(headerOffset - dataOffset); // any alignment writer.Write(headerOffset - indexesOffset); // low 2 bits are ignored writer.Write(headerOffset - ridsOffset); // low 2 bits are ignored } } /// /// CLR 4.0 (.NET 4.0 - 4.5) hot pool writer /// sealed class HotPool40 : HotPool { /// /// Constructor /// /// Pool type public HotPool40(HeapType heapType) : base(heapType) { } /// internal override uint SetOffsetImpl() { uint offs = 0; // data can be anywhere except where rids can be offs = Utils.AlignUp(offs, HP_ALIGNMENT); dataOffset = offs; offs += GetDataSize(); // indexes can be anywhere except where rids can be offs = Utils.AlignUp(offs, HP_ALIGNMENT); indexesOffset = offs; offs += (uint)dataList.Length * 4; // rids must be right before the header offs = Utils.AlignUp(offs, HP_ALIGNMENT); ridsOffset = offs; offs += (uint)dataList.Length * 4; offs = Utils.AlignUp(offs, HP_ALIGNMENT); headerOffset = offs; offs += 3 * 4; return offs; } /// internal override void WriteToImpl(BinaryWriter writer) { uint offs = 0; long startPos = writer.BaseStream.Position; var dataList2 = GetPoolDataOrder(); // Write data writer.WriteZeros((int)(dataOffset - offs)); foreach (var info in dataList2) writer.Write(info.Data); offs = (uint)(writer.BaseStream.Position - startPos); // Write indexes (hot pool offsets) writer.WriteZeros((int)(indexesOffset - offs)); foreach (var info in dataList) writer.Write(info.PoolOffset); offs = (uint)(writer.BaseStream.Position - startPos); // Write rids (heap offsets) writer.WriteZeros((int)(ridsOffset - offs)); foreach (var kv in dataList) writer.Write(kv.HeapOffset); offs = (uint)(writer.BaseStream.Position - startPos); // Write header writer.WriteZeros((int)(headerOffset - offs)); writer.Write(headerOffset - ridsOffset); // must be 4-byte aligned writer.Write(headerOffset - indexesOffset); // must be 4-byte aligned writer.Write(headerOffset - dataOffset); // any alignment } } } dnlib-2.1_VS2010/src/DotNet/Writer/HotTable.cs000066400000000000000000000332531325033663500206640ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.DotNet.MD; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Hot metadata table base class /// public abstract class HotTable : IChunk { /// /// At most 64K rows can be used when only a partial table is stored in the /// hot table. The first level table indexes into the second level table, /// and the index is 16 bits. /// public const int MAX_ROWS = 0x10000; internal const uint HT_ALIGNMENT = 4; FileOffset offset; RVA rva; readonly MetaData metadata; internal readonly IMDTable mdTable; readonly HotHeapVersion version; readonly int hotTableHeaderSize; internal readonly int alignedHotTableHeaderSize; uint totalLength; // full table fields byte[] data; // partial table fields internal List rids; internal Dictionary partialData; internal int shift; uint mask; internal ushort[] firstLevelTable; internal byte[] secondLevelTable; internal uint dataOffset; internal uint firstLevelOffset; internal uint secondLevelOffset; /// /// true if we can write a partial table, false if we must write /// the full table. /// public bool CanWritePartialTable { get { return data == null && rids != null && rids.Count <= MAX_ROWS; } } /// /// Gets the full size of the table /// uint FullTableSize { get { return (uint)(mdTable.Rows * mdTable.TableInfo.RowSize); } } /// /// Gets the table type /// public Table Table { get { return mdTable.Table; } } /// /// Constructor /// /// Metadata owner /// Hot heap version /// The MD table internal HotTable(MetaData metadata, HotHeapVersion version, IMDTable mdTable) { this.metadata = metadata; this.mdTable = mdTable; this.version = version; switch (version) { case HotHeapVersion.CLR20: hotTableHeaderSize = 0x12; break; case HotHeapVersion.CLR40: hotTableHeaderSize = 0x16; break; default: throw new ArgumentException("Invalid hot heap version"); } this.alignedHotTableHeaderSize = Utils.AlignUp(this.hotTableHeaderSize, HT_ALIGNMENT); } /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; mdTable.SetReadOnly(); if (CanWritePartialTable) { InitializePartialData(); totalLength = CalculatePartialTableLength(); } else totalLength = CalculateFullTableLength(); } /// /// Calculates the total size required to write a partial table. It is only called if /// the partial table will be written. /// internal abstract uint CalculatePartialTableLength(); /// /// Calculates the total size required to write a full table. It is only called if /// the full table will be written. /// uint CalculateFullTableLength() { return (uint)alignedHotTableHeaderSize + FullTableSize; } /// public uint GetFileLength() { return totalLength; } /// public uint GetVirtualSize() { return GetFileLength(); } /// /// Adds a row. This method must be called to write a partial table. If too many rows /// are added (see ), then the full table will be written. If this /// method is never called, a full table will be written. /// /// The row ID. This must be the new rid, so this method can only be /// called after the table row has been assigned a new rid. public void Add(uint rid) { if (totalLength != 0) throw new InvalidOperationException("Can't call Add() after SetOffset() has been called"); if (partialData != null || data != null) throw new InvalidOperationException("Can't add data when full/partial data has been created"); if (rid == 0 || rid > (uint)mdTable.Rows) return; if (rids == null) rids = new List(); rids.Add(rid); } /// /// Calls the to write all its rows to a buffer. This is the data /// that will be written to this hot table. If this is not explicitly called, it will /// be implicitly called later when all data must be written. The table will be set to /// read-only. If this method is called, all data will be written to the heap even if /// has been called. /// public void CreateFullData() { mdTable.SetReadOnly(); rids = null; if (data != null) return; data = new byte[FullTableSize]; var writer = new BinaryWriter(new MemoryStream(data)); writer.Write(metadata, mdTable); if (writer.BaseStream.Position != data.Length) throw new InvalidOperationException("Didn't write all MD table data"); } /// /// Creates the partial data of all rows that have been 'd so far. /// If a partial table can't be created, is automatically /// called instead. If this method isn't explicitly called, it will be implicitly called /// later when the partial data must be written. The table will be set to read-only. /// public void CreatePartialData() { mdTable.SetReadOnly(); if (!CanWritePartialTable) { CreateFullData(); return; } InitializePartialData(); var memStream = new MemoryStream(mdTable.TableInfo.RowSize); var writer = new BinaryWriter(memStream); foreach (var rid in rids) { memStream.Position = 0; var row = mdTable.Get(rid); writer.Write(metadata, mdTable, row); partialData[rid] = memStream.ToArray(); } } void InitializePartialData() { if (partialData != null) return; partialData = new Dictionary(rids.Count); foreach (var rid in rids) partialData[rid] = null; InitializePartialRids(); } /// public void WriteTo(BinaryWriter writer) { if (CanWritePartialTable) PartialWriteTo(writer); else FullWriteTo(writer); firstLevelTable = null; secondLevelTable = null; partialData = null; rids = null; data = null; } /// /// Writes the full table to the hot table /// /// Writer void FullWriteTo(BinaryWriter writer) { CreateFullData(); var startPos = writer.BaseStream.Position; writer.Write(mdTable.Rows); // hot records writer.Write(0); // offset of 1st level table writer.Write(0); // offset of 2nd level table if (version == HotHeapVersion.CLR40) writer.Write(0); // offset of indexes table writer.Write(alignedHotTableHeaderSize); // offset of hot data (4-byte aligned) writer.Write((ushort)0); // shift count writer.WriteZeros(alignedHotTableHeaderSize - (int)(writer.BaseStream.Position - startPos)); writer.Write(data); } /// /// Writes the partial table to the hot table /// /// Writer internal abstract void PartialWriteTo(BinaryWriter writer); static int CountMaxBits(uint val) { int bits = 0; while (val != 0) { val >>= 1; bits++; } return bits; } void InitializePartialRids() { shift = CalculateShift(); mask = (1U << shift) - 1; SortRids(); CreateFirstAndSecondLevelTables(); } int CalculateShift() { mdTable.SetReadOnly(); int maxBits = CountMaxBits((uint)mdTable.Rows); if (maxBits >= 16) return maxBits - 8; else return maxBits / 2; } void SortRids() { // Make sure dupes are removed rids.Clear(); rids.AddRange(partialData.Keys); rids.Sort((a, b) => { uint la = a & mask; uint lb = b & mask; if (la != lb) return la.CompareTo(lb); return (a >> shift).CompareTo(b >> shift); }); } void CreateFirstAndSecondLevelTables() { // rids has already been sorted, first on lower bits, then on upper bits firstLevelTable = new ushort[(1 << shift) + 1]; int prevRid = 0, i2 = 0; for (; i2 < partialData.Count; i2++) { int rid = (int)(rids[i2] & mask); while (prevRid <= rid) firstLevelTable[prevRid++] = (ushort)i2; } while (prevRid < firstLevelTable.Length) firstLevelTable[prevRid++] = (ushort)i2; secondLevelTable = new byte[partialData.Count]; for (int i = 0; i < secondLevelTable.Length; i++) secondLevelTable[i] = (byte)(rids[i] >> shift); } /// /// Writes the data /// /// Writer internal void WritePartialData(BinaryWriter writer) { foreach (var rid in rids) writer.Write(partialData[rid]); } /// /// Writes the first level table /// /// Writer internal void WriteFirstLevelTable(BinaryWriter writer) { foreach (var s in firstLevelTable) writer.Write(s); } /// /// Writes the second level table /// /// Writer internal void WriteSecondLevelTable(BinaryWriter writer) { writer.Write(secondLevelTable); } } /// /// CLR 2.0 (.NET 2.0 - 3.5) hot table /// sealed class HotTable20 : HotTable { /// /// Constructor /// /// Metadata owner /// The MD table public HotTable20(MetaData metadata, IMDTable mdTable) : base(metadata, HotHeapVersion.CLR20, mdTable) { } /// internal override uint CalculatePartialTableLength() { uint len = 0; len += (uint)alignedHotTableHeaderSize; // Data len = Utils.AlignUp(len, HT_ALIGNMENT); dataOffset = len; len += (uint)(partialData.Count * mdTable.TableInfo.RowSize); // First level table len = Utils.AlignUp(len, HT_ALIGNMENT); firstLevelOffset = len; len += (uint)(firstLevelTable.Length * 2); // Second level table len = Utils.AlignUp(len, HT_ALIGNMENT); secondLevelOffset = len; len += (uint)secondLevelTable.Length; return len; } /// internal override void PartialWriteTo(BinaryWriter writer) { var startPos = writer.BaseStream.Position; writer.Write(partialData.Count);// hot records writer.Write(firstLevelOffset); // any alignment, all bits are used writer.Write(secondLevelOffset);// any alignment, all bits are used writer.Write(dataOffset); // any alignment, all bits are used writer.Write((ushort)shift);// shift count writer.WriteZeros(alignedHotTableHeaderSize - (int)(writer.BaseStream.Position - startPos)); uint offs; // Data offs = (uint)(writer.BaseStream.Position - startPos); writer.WriteZeros((int)(dataOffset - offs)); WritePartialData(writer); // First level table offs = (uint)(writer.BaseStream.Position - startPos); writer.WriteZeros((int)(firstLevelOffset - offs)); WriteFirstLevelTable(writer); // Second level table offs = (uint)(writer.BaseStream.Position - startPos); writer.WriteZeros((int)(secondLevelOffset - offs)); WriteSecondLevelTable(writer); } } /// /// CLR 4.0 (.NET 4.0 - 4.5) partial hot table /// sealed class HotTable40 : HotTable { uint indexesOffset; /// /// Constructor /// /// Metadata owner /// The MD table public HotTable40(MetaData metadata, IMDTable mdTable) : base(metadata, HotHeapVersion.CLR40, mdTable) { } /// internal override uint CalculatePartialTableLength() { uint len = 0; len += (uint)alignedHotTableHeaderSize; // Data len = Utils.AlignUp(len, HT_ALIGNMENT); dataOffset = len; len += (uint)(partialData.Count * mdTable.TableInfo.RowSize); // First level table len = Utils.AlignUp(len, HT_ALIGNMENT); firstLevelOffset = len; len += (uint)(firstLevelTable.Length * 2); // Second level table len = Utils.AlignUp(len, HT_ALIGNMENT); secondLevelOffset = len; len += (uint)secondLevelTable.Length; // Indexes table len = Utils.AlignUp(len, HT_ALIGNMENT); indexesOffset = len; len += (uint)(partialData.Count * 2); return len; } /// internal override void PartialWriteTo(BinaryWriter writer) { var startPos = writer.BaseStream.Position; writer.Write(partialData.Count);// hot records writer.Write(firstLevelOffset); // any alignment, all bits are used writer.Write(secondLevelOffset);// any alignment, all bits are used writer.Write(indexesOffset);// any alignment, all bits are used writer.Write(dataOffset); // any alignment, all bits are used writer.Write((ushort)shift);// shift count writer.WriteZeros(alignedHotTableHeaderSize - (int)(writer.BaseStream.Position - startPos)); uint offs; // Data offs = (uint)(writer.BaseStream.Position - startPos); writer.WriteZeros((int)(dataOffset - offs)); WritePartialData(writer); // First level table offs = (uint)(writer.BaseStream.Position - startPos); writer.WriteZeros((int)(firstLevelOffset - offs)); WriteFirstLevelTable(writer); // Second level table offs = (uint)(writer.BaseStream.Position - startPos); writer.WriteZeros((int)(secondLevelOffset - offs)); WriteSecondLevelTable(writer); // Indexes table offs = (uint)(writer.BaseStream.Position - startPos); writer.WriteZeros((int)(indexesOffset - offs)); WriteIndexesTable(writer); } void WriteIndexesTable(BinaryWriter writer) { for (int i = 0; i < partialData.Count; i++) writer.Write((ushort)i); } } } dnlib-2.1_VS2010/src/DotNet/Writer/IChunk.cs000066400000000000000000000055571325033663500203510ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Data that gets written to the file /// public interface IChunk { /// /// Gets the file offset. This is valid only after has been called. /// FileOffset FileOffset { get; } /// /// Gets the RVA. This is valid only after has been called. /// RVA RVA { get; } /// /// Called when the file offset and RVA are known /// /// File offset of this chunk /// RVA of this chunk void SetOffset(FileOffset offset, RVA rva); /// /// Gets the raw file length of this chunk. Must only be called after /// has been called. /// /// Length of this chunk uint GetFileLength(); /// /// Gets the virtual size of this chunk. Must only be called after /// has been called. /// /// Virtual size of this chunk uint GetVirtualSize(); /// /// Writes all data to at its current location. It's only /// called after and have been called. /// You cannot assume that 's file position is the same as this /// chunk's file position. /// /// Destination void WriteTo(BinaryWriter writer); } public static partial class Extensions { /// /// Writes all data to and verifies that all bytes were written /// /// this /// Destination /// Not all bytes were written public static void VerifyWriteTo(this IChunk chunk, BinaryWriter writer) { long pos = writer.BaseStream.Position; // Uncomment this to add some debug info, useful when comparing old vs new version //System.Diagnostics.Debug.WriteLine(string.Format(" RVA 0x{0:X8} OFFS 0x{1:X8} VSIZE 0x{2:X8} {3}", (uint)chunk.RVA, (uint)chunk.FileOffset, chunk.GetVirtualSize(), chunk.GetType().FullName)); chunk.WriteTo(writer); if (writer.BaseStream.Position - pos != chunk.GetFileLength()) throw new IOException("Did not write all bytes"); } /// /// Writes a data directory /// /// Writer /// The data internal static void WriteDataDirectory(this BinaryWriter writer, IChunk chunk) { if (chunk == null || chunk.GetVirtualSize() == 0) writer.Write(0UL); else { writer.Write((uint)chunk.RVA); writer.Write(chunk.GetVirtualSize()); } } } } dnlib-2.1_VS2010/src/DotNet/Writer/IHeap.cs000066400000000000000000000007301325033663500201420ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Writer { /// /// .NET Heap interface /// public interface IHeap : IChunk { /// /// Gets the name of the heap /// string Name { get; } /// /// Checks whether the heap is empty /// bool IsEmpty { get; } /// /// Called when the heap should be set to read-only mode /// void SetReadOnly(); } } dnlib-2.1_VS2010/src/DotNet/Writer/IMetaDataListener.cs000066400000000000000000000143021325033663500224530ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Writer { /// /// Gets notified of various events when writing the metadata /// public interface IMetaDataListener { /// /// Called by /// /// The metadata /// Type of metadata event void OnMetaDataEvent(MetaData metaData, MetaDataEvent evt); } /// /// A which does nothing /// public sealed class DummyMetaDataListener : IMetaDataListener { /// /// An instance of this dummy listener /// public static readonly DummyMetaDataListener Instance = new DummyMetaDataListener(); /// public void OnMetaDataEvent(MetaData metaData, MetaDataEvent evt) { } } /// /// All events /// public enum MetaDataEvent { /// /// Creating the tables has just begun /// BeginCreateTables, /// /// Before allocating all TypeDef RIDs /// AllocateTypeDefRids, /// /// Before allocating all MemberDef RIDs /// AllocateMemberDefRids, /// /// Sent by the metadata writer so a UI can update its progress bar /// AllocateMemberDefRids0, /// /// Sent by the metadata writer so a UI can update its progress bar /// AllocateMemberDefRids1, /// /// Sent by the metadata writer so a UI can update its progress bar /// AllocateMemberDefRids2, /// /// Sent by the metadata writer so a UI can update its progress bar /// AllocateMemberDefRids3, /// /// Sent by the metadata writer so a UI can update its progress bar /// AllocateMemberDefRids4, /// /// The rids of types, fields, methods, events, properties and parameters are /// now known. /// MemberDefRidsAllocated, /// /// Sent by the metadata writer so a UI can update its progress bar /// InitializeTypeDefsAndMemberDefs0, /// /// Sent by the metadata writer so a UI can update its progress bar /// InitializeTypeDefsAndMemberDefs1, /// /// Sent by the metadata writer so a UI can update its progress bar /// InitializeTypeDefsAndMemberDefs2, /// /// Sent by the metadata writer so a UI can update its progress bar /// InitializeTypeDefsAndMemberDefs3, /// /// Sent by the metadata writer so a UI can update its progress bar /// InitializeTypeDefsAndMemberDefs4, /// /// The tables and rows of all types, fields, methods, events, properties and parameters /// have been initialized. Method body RVAs are still not known, and no method has been /// written yet. /// MemberDefsInitialized, /// /// Before sorting most tables /// BeforeSortTables, /// /// Most of the tables that should be sorted have been sorted. The CustomAttribute /// table is still unsorted since it's not been created yet. /// MostTablesSorted, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteTypeDefAndMemberDefCustomAttributes0, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteTypeDefAndMemberDefCustomAttributes1, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteTypeDefAndMemberDefCustomAttributes2, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteTypeDefAndMemberDefCustomAttributes3, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteTypeDefAndMemberDefCustomAttributes4, /// /// Custom attributes of all types, fields, methods, events, properties and parameters /// have now been written. /// MemberDefCustomAttributesWritten, /// /// All resources are about to be added to the .NET resources table /// BeginAddResources, /// /// All resources have been added to the .NET resources table /// EndAddResources, /// /// All method bodies are about to be written /// BeginWriteMethodBodies, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteMethodBodies0, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteMethodBodies1, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteMethodBodies2, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteMethodBodies3, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteMethodBodies4, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteMethodBodies5, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteMethodBodies6, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteMethodBodies7, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteMethodBodies8, /// /// Sent by the metadata writer so a UI can update its progress bar /// WriteMethodBodies9, /// /// All method bodies have been written. Their RVAs are still not known. /// EndWriteMethodBodies, /// /// All tables are now sorted, including the CustomAttribute table. /// OnAllTablesSorted, /// /// All tables have been created and all rows populated. The only columns that haven't /// been initialized yet are the ones that are RVAs. /// EndCreateTables, } } dnlib-2.1_VS2010/src/DotNet/Writer/IModuleWriterListener.cs000066400000000000000000000266721325033663500234320ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Writer { /// /// Gets notified of various events when writing a module /// public interface IModuleWriterListener { /// /// Called by and its sub classes. /// /// The module writer /// Type of writer event void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt); } /// /// A which does nothing /// public sealed class DummyModuleWriterListener : IModuleWriterListener { /// /// An instance of this dummy listener /// public static readonly DummyModuleWriterListener Instance = new DummyModuleWriterListener(); /// public void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) { } } /// /// All / events /// public enum ModuleWriterEvent { /// /// Writing has just begun /// Begin, /// /// All PE sections have been created /// PESectionsCreated, /// /// All chunks have been created /// ChunksCreated, /// /// All chunks have been added to their sections /// ChunksAddedToSections, /// /// Original event: . /// Creating the metadata tables has just begun /// MDBeginCreateTables, /// /// Original event: . /// Before allocating all TypeDef RIDs /// MDAllocateTypeDefRids, /// /// Original event: . /// Before allocating all MemberDef RIDs /// MDAllocateMemberDefRids, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDAllocateMemberDefRids0, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDAllocateMemberDefRids1, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDAllocateMemberDefRids2, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDAllocateMemberDefRids3, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDAllocateMemberDefRids4, /// /// Original event: . /// The rids of types, fields, methods, events, properties and parameters are /// now known. /// MDMemberDefRidsAllocated, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDInitializeTypeDefsAndMemberDefs0, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDInitializeTypeDefsAndMemberDefs1, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDInitializeTypeDefsAndMemberDefs2, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDInitializeTypeDefsAndMemberDefs3, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDInitializeTypeDefsAndMemberDefs4, /// /// Original event: . /// The tables and rows of all types, fields, methods, events, properties and parameters /// have been initialized. Method body RVAs are still not known, and no method has been /// written yet. /// MDMemberDefsInitialized, /// /// Original event: . /// Before sorting most tables /// MDBeforeSortTables, /// /// Original event: . /// Most of the tables that should be sorted have been sorted. The CustomAttribute /// table is still unsorted since it's not been created yet. /// MDMostTablesSorted, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteTypeDefAndMemberDefCustomAttributes0, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteTypeDefAndMemberDefCustomAttributes1, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteTypeDefAndMemberDefCustomAttributes2, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteTypeDefAndMemberDefCustomAttributes3, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteTypeDefAndMemberDefCustomAttributes4, /// /// Original event: . /// Custom attributes of all types, fields, methods, events, properties and parameters /// have now been written. /// MDMemberDefCustomAttributesWritten, /// /// Original event: . /// All resources are about to be added to the .NET resources table /// MDBeginAddResources, /// /// Original event: . /// All resources have been added to the .NET resources table /// MDEndAddResources, /// /// Original event: . /// All method bodies are about to be written /// MDBeginWriteMethodBodies, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteMethodBodies0, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteMethodBodies1, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteMethodBodies2, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteMethodBodies3, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteMethodBodies4, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteMethodBodies5, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteMethodBodies6, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteMethodBodies7, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteMethodBodies8, /// /// Original event: . /// Sent by the metadata writer so a UI can update its progress bar /// MDWriteMethodBodies9, /// /// Original event: . /// All method bodies have been written. Their RVAs are still not known. /// MDEndWriteMethodBodies, /// /// Original event: . /// All tables are now sorted, including the CustomAttribute table. /// MDOnAllTablesSorted, /// /// Original event: . /// All tables have been created and all rows populated. The only columns that haven't /// been initialized yet are the ones that are RVAs. /// MDEndCreateTables, /// /// This event occurs before the PDB file is written. This event occurs even if no PDB file /// will be written. /// BeginWritePdb, /// /// The PDB file has been written. This event occurs even if no PDB file has been written. /// EndWritePdb, /// /// This event occurs just before all RVAs and file offsets of the chunks are calculated. /// BeginCalculateRvasAndFileOffsets, /// /// File offsets and RVAs of all chunks are now known. This includes method body and /// field RVAs. Nothing has been written to the destination stream yet. /// EndCalculateRvasAndFileOffsets, /// /// This event occurs before all chunks are written to the destination stream, and after /// all RVAs and file offsets are known. /// BeginWriteChunks, /// /// All chunks have been written to the destination stream. /// EndWriteChunks, /// /// This event occurs before the strong name signature is calculated. This event /// occurs even if the assembly isn't strong name signed. /// BeginStrongNameSign, /// /// This event occurs after the strong name signature has been calculated. This event /// occurs even if the assembly isn't strong name signed. /// EndStrongNameSign, /// /// This event occurs before the checksum in the PE header is updated. This event /// occurs even if the checksum isn't updated. /// BeginWritePEChecksum, /// /// This event occurs after the checksum in the PE header has been updated. This event /// occurs even if the checksum isn't updated. /// EndWritePEChecksum, /// /// Writing has ended /// End, } } dnlib-2.1_VS2010/src/DotNet/Writer/IOffsetHeap.cs000066400000000000000000000023621325033663500213140ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; namespace dnlib.DotNet.Writer { /// /// Interface to get and set raw heap data. Implemented by the offset heaps: #Strings, /// #GUID, #Blob, and #US. /// /// Type of cooked data public interface IOffsetHeap { /// /// Gets the size of the data as raw data when written to the heap /// /// The data /// Size of the data as raw data when written to the heap int GetRawDataSize(TValue data); /// /// Overrides what value should be written to the heap. /// /// Offset of value. Must match an offset returned by /// /// The new raw data. The size must match the raw size exactly. void SetRawData(uint offset, byte[] rawData); /// /// Gets all inserted raw data and their offsets. The returned array /// is owned by the caller. /// /// An enumerable of all raw data and their offsets IEnumerable> GetAllRawData(); } } dnlib-2.1_VS2010/src/DotNet/Writer/IWriterError.cs000066400000000000000000000010621325033663500215520ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Writer { /// /// Gets notified of errors. The default handler should normally throw since the written data /// will probably be invalid. Any error can be ignored. /// public interface IWriterError { /// /// Called when an error is detected (eg. a null pointer or other invalid value). The error /// can be ignored but the written data won't be valid. /// /// Error message void Error(string message); } } dnlib-2.1_VS2010/src/DotNet/Writer/ImageCor20Header.cs000066400000000000000000000070331325033663500221200ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using dnlib.IO; using dnlib.PE; using dnlib.DotNet.MD; namespace dnlib.DotNet.Writer { /// /// Options to /// public sealed class Cor20HeaderOptions { /// /// Default major runtime version /// public const ushort DEFAULT_MAJOR_RT_VER = 2; /// /// Default minor runtime version /// public const ushort DEFAULT_MINOR_RT_VER = 5; /// /// Major runtime version /// public ushort? MajorRuntimeVersion; /// /// Minor runtime version /// public ushort? MinorRuntimeVersion; /// /// Flags /// public ComImageFlags? Flags; /// /// Entry point or null. Either a Method/File token or an RVA. /// public uint? EntryPoint; /// /// Default constructor /// public Cor20HeaderOptions() { } /// /// Constructor /// /// Flags public Cor20HeaderOptions(ComImageFlags flags) { this.Flags = flags; } /// /// Constructor /// /// Major runtime version (default is ) /// Minor runtime version (default is ) /// Flags public Cor20HeaderOptions(ushort major, ushort minor, ComImageFlags flags) { this.MajorRuntimeVersion = major; this.MinorRuntimeVersion = minor; this.Flags = flags; } } /// /// .NET header /// public sealed class ImageCor20Header : IChunk { FileOffset offset; RVA rva; Cor20HeaderOptions options; /// /// Gets/sets the /// public MetaData MetaData { get; set; } /// /// Gets/sets the .NET resources /// public NetResources NetResources { get; set; } /// /// Gets/sets the strong name signature /// public StrongNameSignature StrongNameSignature { get; set; } internal IChunk VtableFixups { get; set; } /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Constructor /// /// Options public ImageCor20Header(Cor20HeaderOptions options) { this.options = options; } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } /// public uint GetFileLength() { return 0x48; } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { writer.Write(0x48); // cb writer.Write(options.MajorRuntimeVersion ?? Cor20HeaderOptions.DEFAULT_MAJOR_RT_VER); writer.Write(options.MinorRuntimeVersion ?? Cor20HeaderOptions.DEFAULT_MINOR_RT_VER); writer.WriteDataDirectory(MetaData); writer.Write((uint)(options.Flags ?? ComImageFlags.ILOnly)); writer.Write(options.EntryPoint ?? 0); writer.WriteDataDirectory(NetResources); writer.WriteDataDirectory(StrongNameSignature); writer.WriteDataDirectory(null); // Code manager table writer.WriteDataDirectory(VtableFixups); writer.WriteDataDirectory(null); // Export address table jumps writer.WriteDataDirectory(null); // Managed native header } } } dnlib-2.1_VS2010/src/DotNet/Writer/ImportAddressTable.cs000066400000000000000000000027041325033663500227070ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Import address table chunk /// public sealed class ImportAddressTable : IChunk { readonly bool is64bit; FileOffset offset; RVA rva; /// /// Gets/sets the /// public ImportDirectory ImportDirectory { get; set; } /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } internal bool Enable { get; set; } /// /// Constructor /// /// true if it's a 64-bit PE file, false if it's a 32-bit PE file public ImportAddressTable(bool is64bit) { this.is64bit = is64bit; } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } /// public uint GetFileLength() { if (!Enable) return 0; return is64bit ? 16U : 8; } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { if (!Enable) return; if (is64bit) { writer.Write((ulong)(uint)ImportDirectory.CorXxxMainRVA); writer.Write(0UL); } else { writer.Write((uint)ImportDirectory.CorXxxMainRVA); writer.Write(0); } } } } dnlib-2.1_VS2010/src/DotNet/Writer/ImportDirectory.cs000066400000000000000000000056631325033663500223250ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using System.Text; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Import directory chunk /// public sealed class ImportDirectory : IChunk { readonly bool is64bit; FileOffset offset; RVA rva; bool isExeFile; uint length; RVA importLookupTableRVA; RVA corXxxMainRVA; RVA mscoreeDllRVA; int stringsPadding; /// /// Gets/sets the /// public ImportAddressTable ImportAddressTable { get; set; } /// /// Gets the RVA of _CorDllMain/_CorExeMain in the import lookup table /// public RVA CorXxxMainRVA { get { return corXxxMainRVA; } } /// /// Gets RVA of _CorExeMain/_CorDllMain in the IAT /// public RVA IatCorXxxMainRVA { get { return ImportAddressTable.RVA; } } /// /// Gets/sets a value indicating whether this is a EXE or a DLL file /// public bool IsExeFile { get { return isExeFile; } set { isExeFile = value; } } /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } internal bool Enable { get; set; } const uint STRINGS_ALIGNMENT = 16; /// /// Constructor /// /// true if it's a 64-bit PE file, false if it's a 32-bit PE file public ImportDirectory(bool is64bit) { this.is64bit = is64bit; } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; length = 0x28; importLookupTableRVA = rva + length; length += is64bit ? 16U : 8; stringsPadding = (int)(rva.AlignUp(STRINGS_ALIGNMENT) - rva); length += (uint)stringsPadding; corXxxMainRVA = rva + length; length += 0xE; mscoreeDllRVA = rva + length; length += 0xC; length++; } /// public uint GetFileLength() { if (!Enable) return 0; return length; } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { if (!Enable) return; writer.Write((uint)importLookupTableRVA); writer.Write(0); // DateTimeStamp writer.Write(0); // ForwarderChain writer.Write((uint)mscoreeDllRVA); // Name writer.Write((uint)ImportAddressTable.RVA); writer.Write(0UL); writer.Write(0UL); writer.Write(0); // ImportLookupTable if (is64bit) { writer.Write((ulong)(uint)corXxxMainRVA); writer.Write(0UL); } else { writer.Write((uint)corXxxMainRVA); writer.Write(0); } writer.WriteZeros(stringsPadding); writer.Write((ushort)0); writer.Write(Encoding.UTF8.GetBytes(IsExeFile ? "_CorExeMain\0" : "_CorDllMain\0")); writer.Write(Encoding.UTF8.GetBytes("mscoree.dll\0")); writer.Write((byte)0); } } } dnlib-2.1_VS2010/src/DotNet/Writer/MDTable.cs000066400000000000000000000120551325033663500204270ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using dnlib.DotNet.MD; namespace dnlib.DotNet.Writer { /// /// MD table interface /// public interface IMDTable { /// /// Gets the table type /// Table Table { get; } /// /// true if the table is empty /// bool IsEmpty { get; } /// /// Gets the number of rows in this table /// int Rows { get; } /// /// Gets/sets a value indicating whether it's sorted /// bool IsSorted { get; set; } /// /// true if has been called /// bool IsReadOnly { get; } /// /// Gets/sets the /// TableInfo TableInfo { get; set; } /// /// Called when the table can't be modified any more /// void SetReadOnly(); /// /// Gets a raw row /// /// Row ID /// The raw row IRawRow Get(uint rid); /// /// Gets all raw rows /// IEnumerable GetRawRows(); } /// /// Creates rows in a table. Rows can optionally be shared to create a compact table. /// /// The raw row type public sealed class MDTable : IMDTable, IEnumerable where T : IRawRow { readonly Table table; readonly Dictionary cachedDict; readonly List cached; TableInfo tableInfo; bool isSorted; bool isReadOnly; /// public Table Table { get { return table; } } /// public bool IsEmpty { get { return cached.Count == 0; } } /// public int Rows { get { return cached.Count; } } /// public bool IsSorted { get { return isSorted; } set { isSorted = value; } } /// public bool IsReadOnly { get { return isReadOnly; } } /// public TableInfo TableInfo { get { return tableInfo; } set { tableInfo = value; } } /// /// Gets the value with rid /// /// The row ID public T this[uint rid] { get { return cached[(int)rid - 1]; } } /// public IRawRow Get(uint rid) { return this[rid]; } /// /// Constructor /// /// The table type /// Equality comparer public MDTable(Table table, IEqualityComparer equalityComparer) { this.table = table; this.cachedDict = new Dictionary(equalityComparer); this.cached = new List(); } /// public void SetReadOnly() { isReadOnly = true; } /// /// Adds a row. If the row already exists, returns a rid to the existing one, else /// it's created and a new rid is returned. /// /// The row. It's now owned by us and must NOT be modified by the caller. /// The RID (row ID) of the row public uint Add(T row) { if (isReadOnly) throw new ModuleWriterException(string.Format("Trying to modify table {0} after it's been set to read-only", table)); uint rid; if (cachedDict.TryGetValue(row, out rid)) return rid; return Create(row); } /// /// Creates a new row even if this row already exists. /// /// The row. It's now owned by us and must NOT be modified by the caller. /// The RID (row ID) of the row public uint Create(T row) { if (isReadOnly) throw new ModuleWriterException(string.Format("Trying to modify table {0} after it's been set to read-only", table)); uint rid = (uint)cached.Count + 1; if (!cachedDict.ContainsKey(row)) cachedDict[row] = rid; cached.Add(row); return rid; } /// /// Re-adds all added rows. Should be called if rows have been modified after being /// inserted. /// public void ReAddRows() { if (isReadOnly) throw new ModuleWriterException(string.Format("Trying to modify table {0} after it's been set to read-only", table)); cachedDict.Clear(); for (int i = 0; i < cached.Count; i++) { uint rid = (uint)i + 1; var row = cached[i]; if (!cachedDict.ContainsKey(row)) cachedDict[row] = rid; } } /// /// Reset the table. /// public void Reset() { if (isReadOnly) throw new ModuleWriterException(string.Format("Trying to modify table {0} after it's been set to read-only", table)); cachedDict.Clear(); cached.Clear(); } /// public IEnumerator GetEnumerator() { return cached.GetEnumerator(); } /// System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } /// public IEnumerable GetRawRows() { foreach (var rawRow in cached) yield return rawRow; } } } dnlib-2.1_VS2010/src/DotNet/Writer/MDTableWriter.cs000066400000000000000000001034431325033663500216260ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Diagnostics; using System.IO; using dnlib.DotNet.MD; namespace dnlib.DotNet.Writer { /// /// Writes s /// public static class MDTableWriter { /// /// Writes a raw row /// /// Writer /// Metadata /// Table /// Row public static void Write(this BinaryWriter writer, MetaData metadata, IMDTable table, IRawRow row) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var col in cols) { if (col.ColumnSize == ColumnSize.Strings) col.Write(writer, stringsHeap.GetOffset(row.Read(col.Index))); else col.Write(writer, row.Read(col.Index)); } } /// /// Writes a metadata table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, IMDTable table) { switch (table.Table) { case Table.Module: writer.Write(metadata, (MDTable)table); break; case Table.TypeRef: writer.Write(metadata, (MDTable)table); break; case Table.TypeDef: writer.Write(metadata, (MDTable)table); break; case Table.FieldPtr: writer.Write(metadata, (MDTable)table); break; case Table.Field: writer.Write(metadata, (MDTable)table); break; case Table.MethodPtr: writer.Write(metadata, (MDTable)table); break; case Table.Method: writer.Write(metadata, (MDTable)table); break; case Table.ParamPtr: writer.Write(metadata, (MDTable)table); break; case Table.Param: writer.Write(metadata, (MDTable)table); break; case Table.InterfaceImpl: writer.Write(metadata, (MDTable)table); break; case Table.MemberRef: writer.Write(metadata, (MDTable)table); break; case Table.Constant: writer.Write(metadata, (MDTable)table); break; case Table.CustomAttribute: writer.Write(metadata, (MDTable)table); break; case Table.FieldMarshal: writer.Write(metadata, (MDTable)table); break; case Table.DeclSecurity: writer.Write(metadata, (MDTable)table); break; case Table.ClassLayout: writer.Write(metadata, (MDTable)table); break; case Table.FieldLayout: writer.Write(metadata, (MDTable)table); break; case Table.StandAloneSig: writer.Write(metadata, (MDTable)table); break; case Table.EventMap: writer.Write(metadata, (MDTable)table); break; case Table.EventPtr: writer.Write(metadata, (MDTable)table); break; case Table.Event: writer.Write(metadata, (MDTable)table); break; case Table.PropertyMap: writer.Write(metadata, (MDTable)table); break; case Table.PropertyPtr: writer.Write(metadata, (MDTable)table); break; case Table.Property: writer.Write(metadata, (MDTable)table); break; case Table.MethodSemantics: writer.Write(metadata, (MDTable)table); break; case Table.MethodImpl: writer.Write(metadata, (MDTable)table); break; case Table.ModuleRef: writer.Write(metadata, (MDTable)table); break; case Table.TypeSpec: writer.Write(metadata, (MDTable)table); break; case Table.ImplMap: writer.Write(metadata, (MDTable)table); break; case Table.FieldRVA: writer.Write(metadata, (MDTable)table); break; case Table.ENCLog: writer.Write(metadata, (MDTable)table); break; case Table.ENCMap: writer.Write(metadata, (MDTable)table); break; case Table.Assembly: writer.Write(metadata, (MDTable)table); break; case Table.AssemblyProcessor: writer.Write(metadata, (MDTable)table); break; case Table.AssemblyOS: writer.Write(metadata, (MDTable)table); break; case Table.AssemblyRef: writer.Write(metadata, (MDTable)table); break; case Table.AssemblyRefProcessor: writer.Write(metadata, (MDTable)table); break; case Table.AssemblyRefOS: writer.Write(metadata, (MDTable)table); break; case Table.File: writer.Write(metadata, (MDTable)table); break; case Table.ExportedType: writer.Write(metadata, (MDTable)table); break; case Table.ManifestResource:writer.Write(metadata, (MDTable)table); break; case Table.NestedClass: writer.Write(metadata, (MDTable)table); break; case Table.GenericParam: writer.Write(metadata, (MDTable)table); break; case Table.MethodSpec: writer.Write(metadata, (MDTable)table); break; case Table.GenericParamConstraint: writer.Write(metadata, (MDTable)table); break; case Table.Document: writer.Write(metadata, (MDTable)table); break; case Table.MethodDebugInformation: writer.Write(metadata, (MDTable)table); break; case Table.LocalScope: writer.Write(metadata, (MDTable)table); break; case Table.LocalVariable: writer.Write(metadata, (MDTable)table); break; case Table.LocalConstant: writer.Write(metadata, (MDTable)table); break; case Table.ImportScope: writer.Write(metadata, (MDTable)table); break; case Table.StateMachineMethod: writer.Write(metadata, (MDTable)table); break; case Table.CustomDebugInformation: writer.Write(metadata, (MDTable)table); break; default: Debug.Fail(string.Format("Unknown table: {0}, add a new method overload", table.Table)); var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table.GetRawRows()) { foreach (var col in cols) { if (col.ColumnSize == ColumnSize.Strings) col.Write(writer, stringsHeap.GetOffset(row.Read(col.Index))); else col.Write(writer, row.Read(col.Index)); } } break; } } /// /// Writes a Module table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { writer.Write(row.Generation); cols[1].Write(writer, stringsHeap.GetOffset(row.Name)); cols[2].Write(writer, row.Mvid); cols[3].Write(writer, row.EncId); cols[4].Write(writer, row.EncBaseId); } } /// /// Writes a TypeRef table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { cols[0].Write(writer, row.ResolutionScope); cols[1].Write(writer, stringsHeap.GetOffset(row.Name)); cols[2].Write(writer, stringsHeap.GetOffset(row.Namespace)); } } /// /// Writes a TypeDef table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { writer.Write(row.Flags); cols[1].Write(writer, stringsHeap.GetOffset(row.Name)); cols[2].Write(writer, stringsHeap.GetOffset(row.Namespace)); cols[3].Write(writer, row.Extends); cols[4].Write(writer, row.FieldList); cols[5].Write(writer, row.MethodList); } } /// /// Writes a FieldPtr table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) cols[0].Write(writer, row.Field); } /// /// Writes a Field table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { writer.Write(row.Flags); cols[1].Write(writer, stringsHeap.GetOffset(row.Name)); cols[2].Write(writer, row.Signature); } } /// /// Writes a MethodPtr table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) cols[0].Write(writer, row.Method); } /// /// Writes a Method table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { writer.Write(row.RVA); writer.Write(row.ImplFlags); writer.Write(row.Flags); cols[3].Write(writer, stringsHeap.GetOffset(row.Name)); cols[4].Write(writer, row.Signature); cols[5].Write(writer, row.ParamList); } } /// /// Writes a ParamPtr table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) cols[0].Write(writer, row.Param); } /// /// Writes a Param table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { writer.Write(row.Flags); writer.Write(row.Sequence); cols[2].Write(writer, stringsHeap.GetOffset(row.Name)); } } /// /// Writes a InterfaceImpl table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.Class); cols[1].Write(writer, row.Interface); } } /// /// Writes a MemberRef table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { cols[0].Write(writer, row.Class); cols[1].Write(writer, stringsHeap.GetOffset(row.Name)); cols[2].Write(writer, row.Signature); } } /// /// Writes a Constant table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { writer.Write(row.Type); writer.Write(row.Padding); cols[2].Write(writer, row.Parent); cols[3].Write(writer, row.Value); } } /// /// Writes a CustomAttribute table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.Parent); cols[1].Write(writer, row.Type); cols[2].Write(writer, row.Value); } } /// /// Writes a FieldMarshal table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.Parent); cols[1].Write(writer, row.NativeType); } } /// /// Writes a DeclSecurity table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { writer.Write(row.Action); cols[1].Write(writer, row.Parent); cols[2].Write(writer, row.PermissionSet); } } /// /// Writes a ClassLayout table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { writer.Write(row.PackingSize); writer.Write(row.ClassSize); cols[2].Write(writer, row.Parent); } } /// /// Writes a FieldLayout table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { writer.Write(row.OffSet); cols[1].Write(writer, row.Field); } } /// /// Writes a StandAloneSig table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) cols[0].Write(writer, row.Signature); } /// /// Writes a EventMap table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.Parent); cols[1].Write(writer, row.EventList); } } /// /// Writes a EventPtr table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) cols[0].Write(writer, row.Event); } /// /// Writes a Event table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { writer.Write(row.EventFlags); cols[1].Write(writer, stringsHeap.GetOffset(row.Name)); cols[2].Write(writer, row.EventType); } } /// /// Writes a PropertyMap table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.Parent); cols[1].Write(writer, row.PropertyList); } } /// /// Writes a PropertyPtr table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) cols[0].Write(writer, row.Property); } /// /// Writes a Property table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { writer.Write(row.PropFlags); cols[1].Write(writer, stringsHeap.GetOffset(row.Name)); cols[2].Write(writer, row.Type); } } /// /// Writes a MethodSemantics table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { writer.Write(row.Semantic); cols[1].Write(writer, row.Method); cols[2].Write(writer, row.Association); } } /// /// Writes a MethodImpl table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.Class); cols[1].Write(writer, row.MethodBody); cols[2].Write(writer, row.MethodDeclaration); } } /// /// Writes a ModuleRef table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) cols[0].Write(writer, stringsHeap.GetOffset(row.Name)); } /// /// Writes a TypeSpec table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) cols[0].Write(writer, row.Signature); } /// /// Writes a ImplMap table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { writer.Write(row.MappingFlags); cols[1].Write(writer, row.MemberForwarded); cols[2].Write(writer, stringsHeap.GetOffset(row.ImportName)); cols[3].Write(writer, row.ImportScope); } } /// /// Writes a FieldRVA table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { writer.Write(row.RVA); cols[1].Write(writer, row.Field); } } /// /// Writes a ENCLog table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { foreach (var row in table) { writer.Write(row.Token); writer.Write(row.FuncCode); } } /// /// Writes a ENCMap table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { foreach (var row in table) writer.Write(row.Token); } /// /// Writes a Assembly table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { writer.Write(row.HashAlgId); writer.Write(row.MajorVersion); writer.Write(row.MinorVersion); writer.Write(row.BuildNumber); writer.Write(row.RevisionNumber); writer.Write(row.Flags); cols[6].Write(writer, row.PublicKey); cols[7].Write(writer, stringsHeap.GetOffset(row.Name)); cols[8].Write(writer, stringsHeap.GetOffset(row.Locale)); } } /// /// Writes a AssemblyProcessor table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { foreach (var row in table) writer.Write(row.Processor); } /// /// Writes a AssemblyOS table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { foreach (var row in table) { writer.Write(row.OSPlatformId); writer.Write(row.OSMajorVersion); writer.Write(row.OSMinorVersion); } } /// /// Writes a AssemblyRef table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { writer.Write(row.MajorVersion); writer.Write(row.MinorVersion); writer.Write(row.BuildNumber); writer.Write(row.RevisionNumber); writer.Write(row.Flags); cols[5].Write(writer, row.PublicKeyOrToken); cols[6].Write(writer, stringsHeap.GetOffset(row.Name)); cols[7].Write(writer, stringsHeap.GetOffset(row.Locale)); cols[8].Write(writer, row.HashValue); } } /// /// Writes a AssemblyRefProcessor table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { writer.Write(row.Processor); cols[1].Write(writer, row.AssemblyRef); } } /// /// Writes a AssemblyRefOS table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { writer.Write(row.OSPlatformId); writer.Write(row.OSMajorVersion); writer.Write(row.OSMinorVersion); cols[3].Write(writer, row.AssemblyRef); } } /// /// Writes a File table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { writer.Write(row.Flags); cols[1].Write(writer, stringsHeap.GetOffset(row.Name)); cols[2].Write(writer, row.HashValue); } } /// /// Writes a ExportedType table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { writer.Write(row.Flags); writer.Write(row.TypeDefId); cols[2].Write(writer, stringsHeap.GetOffset(row.TypeName)); cols[3].Write(writer, stringsHeap.GetOffset(row.TypeNamespace)); cols[4].Write(writer, row.Implementation); } } /// /// Writes a ManifestResource table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { writer.Write(row.Offset); writer.Write(row.Flags); cols[2].Write(writer, stringsHeap.GetOffset(row.Name)); cols[3].Write(writer, row.Implementation); } } /// /// Writes a NestedClass table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.NestedClass); cols[1].Write(writer, row.EnclosingClass); } } /// /// Writes a GenericParam table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; if (cols.Count >= 5) { foreach (var row in table) { writer.Write(row.Number); writer.Write(row.Flags); cols[2].Write(writer, row.Owner); cols[3].Write(writer, stringsHeap.GetOffset(row.Name)); cols[4].Write(writer, row.Kind); } } else { foreach (var row in table) { writer.Write(row.Number); writer.Write(row.Flags); cols[2].Write(writer, row.Owner); cols[3].Write(writer, stringsHeap.GetOffset(row.Name)); } } } /// /// Writes a MethodSpec table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.Method); cols[1].Write(writer, row.Instantiation); } } /// /// Writes a GenericParamConstraint table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.Owner); cols[1].Write(writer, row.Constraint); } } /// /// Writes a Document table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.Name); cols[1].Write(writer, row.HashAlgorithm); cols[2].Write(writer, row.Hash); cols[3].Write(writer, row.Language); } } /// /// Writes a MethodDebugInformation table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.Document); cols[1].Write(writer, row.SequencePoints); } } /// /// Writes a LocalScope table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.Method); cols[1].Write(writer, row.ImportScope); cols[2].Write(writer, row.VariableList); cols[3].Write(writer, row.ConstantList); cols[4].Write(writer, row.StartOffset); cols[5].Write(writer, row.Length); } } /// /// Writes a LocalVariable table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { cols[0].Write(writer, row.Attributes); cols[1].Write(writer, row.Index); cols[2].Write(writer, stringsHeap.GetOffset(row.Name)); } } /// /// Writes a LocalConstant table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; var stringsHeap = metadata.StringsHeap; foreach (var row in table) { cols[0].Write(writer, stringsHeap.GetOffset(row.Name)); cols[1].Write(writer, row.Signature); } } /// /// Writes a ImportScope table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.Parent); cols[1].Write(writer, row.Imports); } } /// /// Writes a StateMachineMethod table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.MoveNextMethod); cols[1].Write(writer, row.KickoffMethod); } } /// /// Writes a CustomDebugInformation table /// /// Writer /// Metadata /// Table public static void Write(this BinaryWriter writer, MetaData metadata, MDTable table) { var cols = table.TableInfo.Columns; foreach (var row in table) { cols[0].Write(writer, row.Parent); cols[1].Write(writer, row.Kind); cols[2].Write(writer, row.Value); } } } } dnlib-2.1_VS2010/src/DotNet/Writer/ManagedExportsWriter.cs000066400000000000000000000472061325033663500233030ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { sealed class ManagedExportsWriter { const uint DEFAULT_VTBL_FIXUPS_ALIGNMENT = 4; const uint DEFAULT_SDATA_ALIGNMENT = 8; const StubType stubType = StubType.Export; readonly string moduleName; readonly Machine machine; readonly RelocDirectory relocDirectory; readonly MetaData metaData; readonly PEHeaders peHeaders; readonly LogError logError; readonly VtableFixupsChunk vtableFixups; readonly StubsChunk stubsChunk; readonly SdataChunk sdataChunk; readonly ExportDir exportDir; readonly List vtables; readonly List allMethodInfos; readonly List sortedOrdinalMethodInfos; readonly List sortedNameMethodInfos; readonly CpuArch cpuArch; uint exportDirOffset; bool Is64Bit { get { return machine == Machine.IA64 || machine == Machine.AMD64 || machine == Machine.ARM64; } } FileOffset ExportDirOffset { get { return sdataChunk.FileOffset + exportDirOffset; } } RVA ExportDirRVA { get { return sdataChunk.RVA + exportDirOffset; } } uint ExportDirSize { get { return 0x28; } } internal bool HasExports { get { return vtables.Count != 0; } } sealed class ExportDir : IChunk { readonly ManagedExportsWriter owner; public FileOffset FileOffset { get { return owner.ExportDirOffset; } } public RVA RVA { get { return owner.ExportDirRVA; } } public ExportDir(ManagedExportsWriter owner) { this.owner = owner; } void IChunk.SetOffset(FileOffset offset, RVA rva) { throw new NotSupportedException(); } public uint GetFileLength() { return owner.ExportDirSize; } public uint GetVirtualSize() { return GetFileLength(); } void IChunk.WriteTo(BinaryWriter writer) { throw new NotSupportedException(); } } sealed class VtableFixupsChunk : IChunk { readonly ManagedExportsWriter owner; FileOffset offset; RVA rva; internal uint length; public FileOffset FileOffset { get { return offset; } } public RVA RVA { get { return rva; } } public VtableFixupsChunk(ManagedExportsWriter owner) { this.owner = owner; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public void WriteTo(BinaryWriter writer) { owner.WriteVtableFixups(writer); } } sealed class StubsChunk : IChunk { readonly ManagedExportsWriter owner; FileOffset offset; RVA rva; internal uint length; public FileOffset FileOffset { get { return offset; } } public RVA RVA { get { return rva; } } public StubsChunk(ManagedExportsWriter owner) { this.owner = owner; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public void WriteTo(BinaryWriter writer) { owner.WriteStubs(writer); } } sealed class SdataChunk : IChunk { readonly ManagedExportsWriter owner; FileOffset offset; RVA rva; internal uint length; public FileOffset FileOffset { get { return offset; } } public RVA RVA { get { return rva; } } public SdataChunk(ManagedExportsWriter owner) { this.owner = owner; } public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } public uint GetFileLength() { return length; } public uint GetVirtualSize() { return GetFileLength(); } public void WriteTo(BinaryWriter writer) { owner.WriteSdata(writer); } } internal delegate void LogError(string format, params object[] args); public ManagedExportsWriter(string moduleName, Machine machine, RelocDirectory relocDirectory, MetaData metaData, PEHeaders peHeaders, LogError logError) { this.moduleName = moduleName; this.machine = machine; this.relocDirectory = relocDirectory; this.metaData = metaData; this.peHeaders = peHeaders; this.logError = logError; vtableFixups = new VtableFixupsChunk(this); stubsChunk = new StubsChunk(this); sdataChunk = new SdataChunk(this); exportDir = new ExportDir(this); vtables = new List(); allMethodInfos = new List(); sortedOrdinalMethodInfos = new List(); sortedNameMethodInfos = new List(); // The error is reported later when we know that there's at least one exported method CpuArch.TryGetCpuArch(machine, out cpuArch); } internal void AddTextChunks(PESection textSection) { textSection.Add(vtableFixups, DEFAULT_VTBL_FIXUPS_ALIGNMENT); if (cpuArch != null) textSection.Add(stubsChunk, cpuArch.GetStubAlignment(stubType)); } internal void AddSdataChunks(PESection sdataSection) { sdataSection.Add(sdataChunk, DEFAULT_SDATA_ALIGNMENT); } internal void InitializeChunkProperties() { if (allMethodInfos.Count == 0) return; peHeaders.ExportDirectory = exportDir; peHeaders.ImageCor20Header.VtableFixups = vtableFixups; } internal void AddExportedMethods(List methods, uint timestamp) { if (methods.Count == 0) return; // Only check for an unsupported machine when we know there's at least one exported method if (cpuArch == null) { logError("The module has exported methods but the CPU architecture isn't supported: {0} (0x{1:X4})", machine, (ushort)machine); return; } if (methods.Count > 0x10000) { logError("Too many methods have been exported. No more than 2^16 methods can be exported. Number of exported methods: {0}", methods.Count); return; } Initialize(methods, timestamp); } sealed class MethodInfo { public readonly MethodDef Method; public readonly uint StubChunkOffset; public int FunctionIndex; public uint ManagedVtblOffset; public uint NameOffset; public int NameIndex; public byte[] NameBytes; public MethodInfo(MethodDef method, uint stubChunkOffset) { Method = method; StubChunkOffset = stubChunkOffset; } } sealed class VTableInfo { public uint SdataChunkOffset { get; set; } public readonly VTableFlags Flags; public readonly List Methods; public VTableInfo(VTableFlags flags) { Flags = flags; Methods = new List(); } } void Initialize(List methods, uint timestamp) { var dict = new Dictionary>(); var baseFlags = Is64Bit ? VTableFlags._64Bit : VTableFlags._32Bit; uint stubOffset = 0; uint stubAlignment = cpuArch.GetStubAlignment(stubType); uint stubCodeOffset = cpuArch.GetStubCodeOffset(stubType); uint stubSize = cpuArch.GetStubSize(stubType); foreach (var method in methods) { var exportInfo = method.ExportInfo; Debug.Assert(exportInfo != null); if (exportInfo == null) continue; var flags = baseFlags; if ((exportInfo.Options & MethodExportInfoOptions.FromUnmanaged) != 0) flags |= VTableFlags.FromUnmanaged; if ((exportInfo.Options & MethodExportInfoOptions.FromUnmanagedRetainAppDomain) != 0) flags |= VTableFlags.FromUnmanagedRetainAppDomain; if ((exportInfo.Options & MethodExportInfoOptions.CallMostDerived) != 0) flags |= VTableFlags.CallMostDerived; List list; if (!dict.TryGetValue((int)flags, out list)) dict.Add((int)flags, list = new List()); if (list.Count == 0 || list[list.Count - 1].Methods.Count >= ushort.MaxValue) list.Add(new VTableInfo(flags)); var info = new MethodInfo(method, stubOffset + stubCodeOffset); allMethodInfos.Add(info); list[list.Count - 1].Methods.Add(info); stubOffset = (stubOffset + stubSize + stubAlignment - 1) & ~(stubAlignment - 1); } foreach (var kv in dict) vtables.AddRange(kv.Value); WriteSdataBlob(timestamp); vtableFixups.length = (uint)vtables.Count * 8; stubsChunk.length = stubOffset; sdataChunk.length = (uint)sdataBytesInfo.Data.Length; uint expectedOffset = 0; foreach (var info in allMethodInfos) { uint currentOffset = info.StubChunkOffset - stubCodeOffset; if (expectedOffset != currentOffset) throw new InvalidOperationException(); cpuArch.WriteStubRelocs(stubType, relocDirectory, stubsChunk, currentOffset); expectedOffset = (currentOffset + stubSize + stubAlignment - 1) & ~(stubAlignment - 1); } if (expectedOffset != stubOffset) throw new InvalidOperationException(); } struct NamesBlob { readonly Dictionary nameOffsets; readonly List names; readonly List methodNameOffsets; uint currentOffset; int methodNamesCount; bool methodNamesIsFrozen; public int MethodNamesCount { get { return methodNamesCount; } } struct NameInfo { public readonly uint Offset; public readonly byte[] Bytes; public NameInfo(uint offset, byte[] bytes) { Offset = offset; Bytes = bytes; } } public NamesBlob(bool dummy) { nameOffsets = new Dictionary(StringComparer.Ordinal); names = new List(); methodNameOffsets = new List(); currentOffset = 0; methodNamesCount = 0; methodNamesIsFrozen = false; } public uint GetMethodNameOffset(string name, out byte[] bytes) { if (methodNamesIsFrozen) throw new InvalidOperationException(); methodNamesCount++; uint offset = GetOffset(name, out bytes); methodNameOffsets.Add(offset); return offset; } public uint GetOtherNameOffset(string name) { methodNamesIsFrozen = true; byte[] bytes; return GetOffset(name, out bytes); } uint GetOffset(string name, out byte[] bytes) { NameInfo nameInfo; if (nameOffsets.TryGetValue(name, out nameInfo)) { bytes = nameInfo.Bytes; return nameInfo.Offset; } bytes = GetNameASCIIZ(name); names.Add(bytes); uint offset = currentOffset; nameOffsets.Add(name, new NameInfo(offset, bytes)); currentOffset += (uint)bytes.Length; return offset; } // If this method gets updated, also update the reader (MethodExportInfoProvider) static byte[] GetNameASCIIZ(string name) { Debug.Assert(name != null); int size = Encoding.UTF8.GetByteCount(name); var bytes = new byte[size + 1]; Encoding.UTF8.GetBytes(name, 0, name.Length, bytes, 0); if (bytes[bytes.Length - 1] != 0) throw new ModuleWriterException(); return bytes; } public void Write(BinaryWriter writer) { foreach (var name in names) writer.Write(name); } public uint[] GetMethodNameOffsets() { return methodNameOffsets.ToArray(); } } struct SdataBytesInfo { public byte[] Data; public uint namesBlobStreamOffset; public uint moduleNameOffset; public uint exportDirModuleNameStreamOffset; public uint exportDirAddressOfFunctionsStreamOffset; public uint addressOfFunctionsStreamOffset; public uint addressOfNamesStreamOffset; public uint addressOfNameOrdinalsStreamOffset; public uint[] MethodNameOffsets; } SdataBytesInfo sdataBytesInfo; /// /// Writes the .sdata blob. We could write the data in any order, but we write the data in the same order as ILASM /// /// PE timestamp void WriteSdataBlob(uint timestamp) { var stream = new MemoryStream(); var writer = new BinaryWriter(stream); // Write all vtables (referenced from the .text section) Debug.Assert((writer.BaseStream.Position & 7) == 0); foreach (var vtbl in vtables) { vtbl.SdataChunkOffset = (uint)writer.BaseStream.Position; foreach (var info in vtbl.Methods) { info.ManagedVtblOffset = (uint)writer.BaseStream.Position; writer.Write(0x06000000 + metaData.GetRid(info.Method)); if ((vtbl.Flags & VTableFlags._64Bit) != 0) writer.Write(0U); } } var namesBlob = new NamesBlob(1 == 2); int nameIndex = 0; bool error = false; foreach (var info in allMethodInfos) { var exportInfo = info.Method.ExportInfo; var name = exportInfo.Name; if (name == null) { if (exportInfo.Ordinal != null) { sortedOrdinalMethodInfos.Add(info); continue; } name = info.Method.Name; } if (string.IsNullOrEmpty(name)) { error = true; logError("Exported method name is null or empty, method: {0} (0x{1:X8})", info.Method, info.Method.MDToken.Raw); continue; } info.NameOffset = namesBlob.GetMethodNameOffset(name, out info.NameBytes); info.NameIndex = nameIndex++; sortedNameMethodInfos.Add(info); } Debug.Assert(error || sortedOrdinalMethodInfos.Count + sortedNameMethodInfos.Count == allMethodInfos.Count); sdataBytesInfo.MethodNameOffsets = namesBlob.GetMethodNameOffsets(); Debug.Assert(sortedNameMethodInfos.Count == sdataBytesInfo.MethodNameOffsets.Length); sdataBytesInfo.moduleNameOffset = namesBlob.GetOtherNameOffset(moduleName); sortedOrdinalMethodInfos.Sort((a, b) => a.Method.ExportInfo.Ordinal.Value.CompareTo(b.Method.ExportInfo.Ordinal.Value)); sortedNameMethodInfos.Sort((a, b) => CompareTo(a.NameBytes, b.NameBytes)); int ordinalBase, nextFreeOrdinal; if (sortedOrdinalMethodInfos.Count == 0) { ordinalBase = 0; nextFreeOrdinal = 0; } else { ordinalBase = sortedOrdinalMethodInfos[0].Method.ExportInfo.Ordinal.Value; nextFreeOrdinal = sortedOrdinalMethodInfos[sortedOrdinalMethodInfos.Count - 1].Method.ExportInfo.Ordinal.Value + 1; } int nameFuncBaseIndex = nextFreeOrdinal - ordinalBase; int lastFuncIndex = 0; for (int i = 0; i < sortedOrdinalMethodInfos.Count; i++) { int index = sortedOrdinalMethodInfos[i].Method.ExportInfo.Ordinal.Value - ordinalBase; sortedOrdinalMethodInfos[i].FunctionIndex = index; lastFuncIndex = index; } for (int i = 0; i < sortedNameMethodInfos.Count; i++) { lastFuncIndex = nameFuncBaseIndex + i; sortedNameMethodInfos[i].FunctionIndex = lastFuncIndex; } int funcSize = lastFuncIndex + 1; if (funcSize > 0x10000) { logError("Exported function array is too big"); return; } // Write IMAGE_EXPORT_DIRECTORY Debug.Assert((writer.BaseStream.Position & 3) == 0); exportDirOffset = (uint)writer.BaseStream.Position; writer.Write(0U); // Characteristics writer.Write(timestamp); writer.Write(0U); // MajorVersion, MinorVersion sdataBytesInfo.exportDirModuleNameStreamOffset = (uint)writer.BaseStream.Position; writer.Write(0U); // Name writer.Write(ordinalBase); // Base writer.Write((uint)funcSize); // NumberOfFunctions writer.Write(sdataBytesInfo.MethodNameOffsets.Length); // NumberOfNames sdataBytesInfo.exportDirAddressOfFunctionsStreamOffset = (uint)writer.BaseStream.Position; writer.Write(0U); // AddressOfFunctions writer.Write(0U); // AddressOfNames writer.Write(0U); // AddressOfNameOrdinals sdataBytesInfo.addressOfFunctionsStreamOffset = (uint)writer.BaseStream.Position; WriteZeroes(writer, funcSize * 4); sdataBytesInfo.addressOfNamesStreamOffset = (uint)writer.BaseStream.Position; WriteZeroes(writer, sdataBytesInfo.MethodNameOffsets.Length * 4); sdataBytesInfo.addressOfNameOrdinalsStreamOffset = (uint)writer.BaseStream.Position; WriteZeroes(writer, sdataBytesInfo.MethodNameOffsets.Length * 2); sdataBytesInfo.namesBlobStreamOffset = (uint)writer.BaseStream.Position; namesBlob.Write(writer); sdataBytesInfo.Data = stream.ToArray(); } void WriteSdata(BinaryWriter writer) { if (sdataBytesInfo.Data == null) return; PatchSdataBytesBlob(); writer.Write(sdataBytesInfo.Data); } void PatchSdataBytesBlob() { uint rva = (uint)sdataChunk.RVA; uint namesBaseOffset = rva + sdataBytesInfo.namesBlobStreamOffset; var writer = new BinaryWriter(new MemoryStream(sdataBytesInfo.Data)); writer.BaseStream.Position = sdataBytesInfo.exportDirModuleNameStreamOffset; writer.Write(namesBaseOffset + sdataBytesInfo.moduleNameOffset); writer.BaseStream.Position = sdataBytesInfo.exportDirAddressOfFunctionsStreamOffset; writer.Write(rva + sdataBytesInfo.addressOfFunctionsStreamOffset); // AddressOfFunctions if (sdataBytesInfo.MethodNameOffsets.Length != 0) { writer.Write(rva + sdataBytesInfo.addressOfNamesStreamOffset); // AddressOfNames writer.Write(rva + sdataBytesInfo.addressOfNameOrdinalsStreamOffset); // AddressOfNameOrdinals } uint funcBaseRva = (uint)stubsChunk.RVA; writer.BaseStream.Position = sdataBytesInfo.addressOfFunctionsStreamOffset; int currentFuncIndex = 0; foreach (var info in sortedOrdinalMethodInfos) { int zeroes = info.FunctionIndex - currentFuncIndex; if (zeroes < 0) throw new InvalidOperationException(); while (zeroes-- > 0) writer.Write(0); writer.Write(funcBaseRva + info.StubChunkOffset); currentFuncIndex = info.FunctionIndex + 1; } foreach (var info in sortedNameMethodInfos) { if (info.FunctionIndex != currentFuncIndex++) throw new InvalidOperationException(); writer.Write(funcBaseRva + info.StubChunkOffset); } var nameOffsets = sdataBytesInfo.MethodNameOffsets; if (nameOffsets.Length != 0) { writer.BaseStream.Position = sdataBytesInfo.addressOfNamesStreamOffset; foreach (var info in sortedNameMethodInfos) writer.Write(namesBaseOffset + nameOffsets[info.NameIndex]); writer.BaseStream.Position = sdataBytesInfo.addressOfNameOrdinalsStreamOffset; foreach (var info in sortedNameMethodInfos) writer.Write((ushort)info.FunctionIndex); } } static void WriteZeroes(BinaryWriter writer, int count) { while (count >= 8) { writer.Write(0UL); count -= 8; } for (int i = 0; i < count; i++) writer.Write((byte)0); } void WriteVtableFixups(BinaryWriter writer) { if (vtables.Count == 0) return; foreach (var vtbl in vtables) { Debug.Assert(vtbl.Methods.Count <= ushort.MaxValue); writer.Write((uint)sdataChunk.RVA + vtbl.SdataChunkOffset); writer.Write((ushort)vtbl.Methods.Count); writer.Write((ushort)vtbl.Flags); } } void WriteStubs(BinaryWriter writer) { if (vtables.Count == 0) return; if (cpuArch == null) return; ulong imageBase = peHeaders.ImageBase; uint stubsBaseRva = (uint)stubsChunk.RVA; uint vtblBaseRva = (uint)sdataChunk.RVA; uint expectedOffset = 0; uint stubCodeOffset = cpuArch.GetStubCodeOffset(stubType); uint stubSize = cpuArch.GetStubSize(stubType); uint stubAlignment = cpuArch.GetStubAlignment(stubType); int zeroes = (int)((stubSize + stubAlignment - 1 & ~(stubAlignment - 1)) - stubSize); foreach (var info in allMethodInfos) { uint currentOffset = info.StubChunkOffset - stubCodeOffset; if (expectedOffset != currentOffset) throw new InvalidOperationException(); var pos = writer.BaseStream.Position; cpuArch.WriteStub(stubType, writer, imageBase, stubsBaseRva + currentOffset, vtblBaseRva + info.ManagedVtblOffset); Debug.Assert(pos + stubSize == writer.BaseStream.Position, "The full stub wasn't written"); if (pos + stubSize != writer.BaseStream.Position) throw new InvalidOperationException(); if (zeroes != 0) WriteZeroes(writer, zeroes); expectedOffset = (currentOffset + stubSize + stubAlignment - 1) & ~(stubAlignment - 1); } if (expectedOffset != stubsChunk.length) throw new InvalidOperationException(); } static int CompareTo(byte[] a, byte[] b) { if (a == b) return 0; int max = Math.Min(a.Length, b.Length); for (int i = 0; i < max; i++) { int c = a[i] - b[i]; if (c != 0) return c; } return a.Length - b.Length; } } } dnlib-2.1_VS2010/src/DotNet/Writer/MarshalBlobWriter.cs000066400000000000000000000107441325033663500225450ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; namespace dnlib.DotNet.Writer { /// /// Writes field marshal blobs /// public struct MarshalBlobWriter : IDisposable, IFullNameCreatorHelper { readonly ModuleDef module; readonly MemoryStream outStream; readonly BinaryWriter writer; readonly IWriterError helper; /// /// Creates a field marshal blob from /// /// Owner module /// Marshal type /// Helps this class /// A field marshal blob or null if is /// null public static byte[] Write(ModuleDef module, MarshalType marshalType, IWriterError helper) { using (var writer = new MarshalBlobWriter(module, helper)) return writer.Write(marshalType); } MarshalBlobWriter(ModuleDef module, IWriterError helper) { this.module = module; this.outStream = new MemoryStream(); this.writer = new BinaryWriter(outStream); this.helper = helper; } byte[] Write(MarshalType marshalType) { if (marshalType == null) return null; var type = marshalType.NativeType; if (type != NativeType.RawBlob) { if ((uint)type > byte.MaxValue) helper.Error("Invalid MarshalType.NativeType"); writer.Write((byte)type); } bool canWrite = true; switch (type) { case NativeType.FixedSysString: var fixedSysString = (FixedSysStringMarshalType)marshalType; if (fixedSysString.IsSizeValid) WriteCompressedUInt32((uint)fixedSysString.Size); break; case NativeType.SafeArray: var safeArray = (SafeArrayMarshalType)marshalType; if (UpdateCanWrite(safeArray.IsVariantTypeValid, "VariantType", ref canWrite)) WriteCompressedUInt32((uint)safeArray.VariantType); if (UpdateCanWrite(safeArray.IsUserDefinedSubTypeValid, "UserDefinedSubType", ref canWrite)) Write(safeArray.UserDefinedSubType.AssemblyQualifiedName); break; case NativeType.FixedArray: var fixedArray = (FixedArrayMarshalType)marshalType; if (UpdateCanWrite(fixedArray.IsSizeValid, "Size", ref canWrite)) WriteCompressedUInt32((uint)fixedArray.Size); if (UpdateCanWrite(fixedArray.IsElementTypeValid, "ElementType", ref canWrite)) WriteCompressedUInt32((uint)fixedArray.ElementType); break; case NativeType.Array: var array = (ArrayMarshalType)marshalType; if (UpdateCanWrite(array.IsElementTypeValid, "ElementType", ref canWrite)) WriteCompressedUInt32((uint)array.ElementType); if (UpdateCanWrite(array.IsParamNumberValid, "ParamNumber", ref canWrite)) WriteCompressedUInt32((uint)array.ParamNumber); if (UpdateCanWrite(array.IsSizeValid, "Size", ref canWrite)) WriteCompressedUInt32((uint)array.Size); if (UpdateCanWrite(array.IsFlagsValid, "Flags", ref canWrite)) WriteCompressedUInt32((uint)array.Flags); break; case NativeType.CustomMarshaler: var custMarshaler = (CustomMarshalType)marshalType; Write(custMarshaler.Guid); Write(custMarshaler.NativeTypeName); var cm = custMarshaler.CustomMarshaler; var cmName = cm == null ? string.Empty : FullNameCreator.AssemblyQualifiedName(cm, this); Write(cmName); Write(custMarshaler.Cookie); break; case NativeType.IUnknown: case NativeType.IDispatch: case NativeType.IntF: var iface = (InterfaceMarshalType)marshalType; if (iface.IsIidParamIndexValid) WriteCompressedUInt32((uint)iface.IidParamIndex); break; case NativeType.RawBlob: var data = ((RawMarshalType)marshalType).Data; if (data != null) writer.Write(data); break; default: break; } writer.Flush(); return outStream.ToArray(); } bool UpdateCanWrite(bool isValid, string field, ref bool canWriteMore) { if (!canWriteMore) { if (isValid) helper.Error(string.Format("MarshalType field {0} is valid even though a previous field was invalid", field)); return canWriteMore; } if (!isValid) canWriteMore = false; return canWriteMore; } uint WriteCompressedUInt32(uint value) { return writer.WriteCompressedUInt32(helper, value); } void Write(UTF8String s) { writer.Write(helper, s); } /// public void Dispose() { if (outStream != null) outStream.Dispose(); } bool IFullNameCreatorHelper.MustUseAssemblyName(IType type) { return FullNameCreator.MustUseAssemblyName(module, type); } } } dnlib-2.1_VS2010/src/DotNet/Writer/MaxStackCalculator.cs000066400000000000000000000110051325033663500226760ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using dnlib.DotNet.Emit; namespace dnlib.DotNet.Writer { /// /// Calculates max stack usage by using a simple pass over all instructions. This value /// can be placed in the fat method header's MaxStack field. /// public struct MaxStackCalculator { IList instructions; IList exceptionHandlers; readonly Dictionary stackHeights; int errors; /// /// Gets max stack value /// /// All instructions /// All exception handlers /// Max stack value public static uint GetMaxStack(IList instructions, IList exceptionHandlers) { uint maxStack; new MaxStackCalculator(instructions, exceptionHandlers).Calculate(out maxStack); return maxStack; } /// /// Gets max stack value /// /// All instructions /// All exception handlers /// Updated with max stack value /// true if no errors were detected, false otherwise public static bool GetMaxStack(IList instructions, IList exceptionHandlers, out uint maxStack) { return new MaxStackCalculator(instructions, exceptionHandlers).Calculate(out maxStack); } internal static MaxStackCalculator Create() { return new MaxStackCalculator(true); } MaxStackCalculator(bool dummy) { this.instructions = null; this.exceptionHandlers = null; this.stackHeights = new Dictionary(); this.errors = 0; } MaxStackCalculator(IList instructions, IList exceptionHandlers) { this.instructions = instructions; this.exceptionHandlers = exceptionHandlers; this.stackHeights = new Dictionary(); this.errors = 0; } internal void Reset(IList instructions, IList exceptionHandlers) { this.instructions = instructions; this.exceptionHandlers = exceptionHandlers; stackHeights.Clear(); errors = 0; } internal bool Calculate(out uint maxStack) { foreach (var eh in exceptionHandlers) { if (eh == null) continue; if (eh.TryStart != null) stackHeights[eh.TryStart] = 0; if (eh.FilterStart != null) stackHeights[eh.FilterStart] = 1; if (eh.HandlerStart != null) { bool pushed = eh.HandlerType == ExceptionHandlerType.Catch || eh.HandlerType == ExceptionHandlerType.Filter; stackHeights[eh.HandlerStart] = pushed ? 1 : 0; } } int stack = 0; bool resetStack = false; foreach (var instr in instructions) { if (instr == null) continue; if (resetStack) { stackHeights.TryGetValue(instr, out stack); resetStack = false; } stack = WriteStack(instr, stack); if (instr.OpCode.Code == Code.Jmp) { if (stack != 0) errors++; } else { int pushes, pops; instr.CalculateStackUsage(out pushes, out pops); if (pops == -1) stack = 0; else { stack -= pops; if (stack < 0) { errors++; stack = 0; } stack += pushes; } } if (stack < 0) { errors++; stack = 0; } switch (instr.OpCode.FlowControl) { case FlowControl.Branch: WriteStack(instr.Operand as Instruction, stack); resetStack = true; break; case FlowControl.Call: if (instr.OpCode.Code == Code.Jmp) resetStack = true; break; case FlowControl.Cond_Branch: if (instr.OpCode.Code == Code.Switch) { var targets = instr.Operand as IList; if (targets != null) { foreach (var target in targets) WriteStack(target, stack); } } else WriteStack(instr.Operand as Instruction, stack); break; case FlowControl.Return: case FlowControl.Throw: resetStack = true; break; } } stack = 0; foreach (var v in stackHeights.Values) stack = Math.Max(stack, v); maxStack = (uint)stack; return errors == 0; } int WriteStack(Instruction instr, int stack) { if (instr == null) { errors++; return stack; } int stack2; if (stackHeights.TryGetValue(instr, out stack2)) { if (stack != stack2) errors++; return stack2; } stackHeights[instr] = stack; return stack; } } } dnlib-2.1_VS2010/src/DotNet/Writer/MetaData.cs000066400000000000000000003433101325033663500206400ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using System.Text; using dnlib.IO; using dnlib.PE; using dnlib.DotNet.MD; using dnlib.DotNet.Emit; using System.Diagnostics; using dnlib.DotNet.Pdb; using dnlib.DotNet.Pdb.Portable; namespace dnlib.DotNet.Writer { /// /// flags /// [Flags] public enum MetaDataFlags : uint { /// /// Preserves all rids in the TypeRef table /// PreserveTypeRefRids = 1, /// /// Preserves all rids in the TypeDef table /// PreserveTypeDefRids = 2, /// /// Preserves all rids in the Field table /// PreserveFieldRids = 4, /// /// Preserves all rids in the Method table /// PreserveMethodRids = 8, /// /// Preserves all rids in the Param table /// PreserveParamRids = 0x10, /// /// Preserves all rids in the MemberRef table /// PreserveMemberRefRids = 0x20, /// /// Preserves all rids in the StandAloneSig table /// PreserveStandAloneSigRids = 0x40, /// /// Preserves all rids in the Event table /// PreserveEventRids = 0x80, /// /// Preserves all rids in the Property table /// PreservePropertyRids = 0x100, /// /// Preserves all rids in the TypeSpec table /// PreserveTypeSpecRids = 0x200, /// /// Preserves all rids in the MethodSpec table /// PreserveMethodSpecRids = 0x400, /// /// Preserves all method rids, i.e., Method, MemberRef and /// MethodSpec rids. /// PreserveAllMethodRids = PreserveMethodRids | PreserveMemberRefRids | PreserveMethodSpecRids, /// /// Preserves all rids in the following tables: TypeRef, TypeDef, /// Field, Method, Param, MemberRef, StandAloneSig, /// Event, Property, TypeSpec, MethodSpec /// PreserveRids = PreserveTypeRefRids | PreserveTypeDefRids | PreserveFieldRids | PreserveMethodRids | PreserveParamRids | PreserveMemberRefRids | PreserveStandAloneSigRids | PreserveEventRids | PreservePropertyRids | PreserveTypeSpecRids | PreserveMethodSpecRids, /// /// Preserves all offsets in the #Strings heap (the original #Strings heap will be saved /// in the new file). Type names, field names, and other non-user strings are stored /// in the #Strings heap. /// PreserveStringsOffsets = 0x800, /// /// Preserves all offsets in the #US heap (the original #US heap will be saved /// in the new file). User strings (referenced by the ldstr instruction) are stored in /// the #US heap. /// PreserveUSOffsets = 0x1000, /// /// Preserves all offsets in the #Blob heap (the original #Blob heap will be saved /// in the new file). Custom attributes, signatures and other blobs are stored in the /// #Blob heap. /// PreserveBlobOffsets = 0x2000, /// /// Preserves the extra data that is present after the original signature in the #Blob /// heap. This extra data shouldn't be present but might be present if an obfuscator /// has added this extra data and is eg. using it to decrypt stuff. /// PreserveExtraSignatureData = 0x4000, /// /// Preserves as much as possible /// PreserveAll = PreserveRids | PreserveStringsOffsets | PreserveUSOffsets | PreserveBlobOffsets | PreserveExtraSignatureData, /// /// The original method body's max stack field should be used and a new one should not /// be calculated. /// KeepOldMaxStack = 0x8000, /// /// Always create the #GUID heap even if it's empty /// AlwaysCreateGuidHeap = 0x10000, /// /// Always create the #Strings heap even if it's empty /// AlwaysCreateStringsHeap = 0x20000, /// /// Always create the #US heap even if it's empty /// AlwaysCreateUSHeap = 0x40000, /// /// Always create the #Blob heap even if it's empty /// AlwaysCreateBlobHeap = 0x80000, /// /// Sort the InterfaceImpl table the same way Roslyn sorts it. Roslyn doesn't sort it /// according to the ECMA spec, see https://github.com/dotnet/roslyn/issues/3905 /// RoslynSortInterfaceImpl = 0x100000, } /// /// options /// public sealed class MetaDataOptions { MetaDataHeaderOptions metaDataHeaderOptions; MetaDataHeaderOptions debugMetaDataHeaderOptions; TablesHeapOptions tablesHeapOptions; List otherHeaps; List otherHeapsEnd; /// /// Gets/sets the options. This is never null. /// public MetaDataHeaderOptions MetaDataHeaderOptions { get { return metaDataHeaderOptions ?? (metaDataHeaderOptions = new MetaDataHeaderOptions()); } set { metaDataHeaderOptions = value; } } /// /// Gets/sets the debug (portable PDB) options. This is never null. /// public MetaDataHeaderOptions DebugMetaDataHeaderOptions { get { return debugMetaDataHeaderOptions ?? (debugMetaDataHeaderOptions = MetaDataHeaderOptions.CreatePortablePdbV1_0()); } set { debugMetaDataHeaderOptions = value; } } /// /// Gets/sets the options. This is never null. /// public TablesHeapOptions TablesHeapOptions { get { return tablesHeapOptions ?? (tablesHeapOptions = new TablesHeapOptions()); } set { tablesHeapOptions = value; } } /// /// Gets/sets the debug (portable PDB) options. This is never null. /// public TablesHeapOptions DebugTablesHeapOptions { get { return tablesHeapOptions ?? (tablesHeapOptions = TablesHeapOptions.CreatePortablePdbV1_0()); } set { tablesHeapOptions = value; } } /// /// Various options /// public MetaDataFlags Flags; /// /// Any additional heaps that should be added to the beginning of the heaps list /// public List OtherHeaps { get { return otherHeaps ?? (otherHeaps = new List()); } } /// /// Any additional heaps that should be added to end of the heaps list /// public List OtherHeapsEnd { get { return otherHeapsEnd ?? (otherHeapsEnd = new List()); } } /// /// Default constructor /// public MetaDataOptions() { } /// /// Constructor /// /// Flags public MetaDataOptions(MetaDataFlags flags) { this.Flags = flags; } /// /// Constructor /// /// Meta data header options public MetaDataOptions(MetaDataHeaderOptions mdhOptions) { this.metaDataHeaderOptions = mdhOptions; } /// /// Constructor /// /// Meta data header options /// Flags public MetaDataOptions(MetaDataHeaderOptions mdhOptions, MetaDataFlags flags) { this.Flags = flags; this.metaDataHeaderOptions = mdhOptions; } } sealed class BinaryWriterContext { public readonly MemoryStream OutStream; public readonly BinaryWriter Writer; public BinaryWriterContext() { OutStream = new MemoryStream(); Writer = new BinaryWriter(OutStream); } } /// /// Portable PDB metadata kind /// public enum DebugMetaDataKind { /// /// No debugging metadata /// None, /// /// Standalone / embedded portable PDB metadata /// Standalone, } /// /// .NET meta data /// public abstract class MetaData : IChunk, ISignatureWriterHelper, ITokenCreator, ICustomAttributeWriterHelper, IPortablePdbCustomDebugInfoWriterHelper { uint length; FileOffset offset; RVA rva; readonly MetaDataOptions options; IMetaDataListener listener; ILogger logger; readonly NormalMetaData debugMetaData; readonly bool isStandaloneDebugMetadata; internal readonly ModuleDef module; internal readonly UniqueChunkList constants; internal readonly MethodBodyChunks methodBodies; internal readonly NetResources netResources; internal readonly MetaDataHeader metaDataHeader; internal HotHeap hotHeap; internal readonly PdbHeap pdbHeap; internal readonly TablesHeap tablesHeap; internal readonly StringsHeap stringsHeap; internal readonly USHeap usHeap; internal readonly GuidHeap guidHeap; internal readonly BlobHeap blobHeap; internal List allTypeDefs; internal readonly Rows moduleDefInfos = new Rows(); internal readonly SortedRows interfaceImplInfos = new SortedRows(); internal readonly SortedRows hasConstantInfos = new SortedRows(); internal readonly SortedRows customAttributeInfos = new SortedRows(); internal readonly SortedRows fieldMarshalInfos = new SortedRows(); internal readonly SortedRows declSecurityInfos = new SortedRows(); internal readonly SortedRows classLayoutInfos = new SortedRows(); internal readonly SortedRows fieldLayoutInfos = new SortedRows(); internal readonly Rows eventMapInfos = new Rows(); internal readonly Rows propertyMapInfos = new Rows(); internal readonly SortedRows methodSemanticsInfos = new SortedRows(); internal readonly SortedRows methodImplInfos = new SortedRows(); internal readonly Rows moduleRefInfos = new Rows(); internal readonly SortedRows implMapInfos = new SortedRows(); internal readonly SortedRows fieldRVAInfos = new SortedRows(); internal readonly Rows assemblyInfos = new Rows(); internal readonly Rows assemblyRefInfos = new Rows(); internal readonly Rows fileDefInfos = new Rows(); internal readonly Rows exportedTypeInfos = new Rows(); internal readonly Rows manifestResourceInfos = new Rows(); internal readonly SortedRows nestedClassInfos = new SortedRows(); internal readonly SortedRows genericParamInfos = new SortedRows(); internal readonly SortedRows genericParamConstraintInfos = new SortedRows(); internal readonly Dictionary methodToBody = new Dictionary(); internal readonly Dictionary methodToNativeBody = new Dictionary(); internal readonly Dictionary embeddedResourceToByteArray = new Dictionary(); readonly Dictionary fieldToInitialValue = new Dictionary(); readonly Rows pdbDocumentInfos = new Rows(); bool methodDebugInformationInfosUsed; readonly SortedRows localScopeInfos = new SortedRows(); readonly Rows localVariableInfos = new Rows(); readonly Rows localConstantInfos = new Rows(); readonly Rows importScopeInfos = new Rows(); readonly SortedRows stateMachineMethodInfos = new SortedRows(); readonly SortedRows customDebugInfos = new SortedRows(); readonly List binaryWriterContexts = new List(); readonly List serializerMethodContexts = new List(); readonly List exportedMethods = new List(); /// /// Gets/sets the listener /// public IMetaDataListener Listener { get { return listener ?? (listener = DummyMetaDataListener.Instance); } set { listener = value; } } /// /// Gets/sets the logger /// public ILogger Logger { get { return logger; } set { logger = value; } } /// /// Gets the module /// public ModuleDef Module { get { return module; } } /// /// Gets the constants /// public UniqueChunkList Constants { get { return constants; } } /// /// Gets the method body chunks /// public MethodBodyChunks MethodBodyChunks { get { return methodBodies; } } /// /// Gets the .NET resources /// public NetResources NetResources { get { return netResources; } } /// /// Gets the MD header /// public MetaDataHeader MetaDataHeader { get { return metaDataHeader; } } /// /// Gets/sets the hot heap (#!) /// HotHeap HotHeap { get { return hotHeap; } set { hotHeap = value; } } /// /// Gets the tables heap. Access to this heap is not recommended, but is useful if you /// want to add random table entries. /// public TablesHeap TablesHeap { get { return tablesHeap; } } /// /// Gets the #Strings heap. Access to this heap is not recommended, but is useful if you /// want to add random strings. /// public StringsHeap StringsHeap { get { return stringsHeap; } } /// /// Gets the #US heap. Access to this heap is not recommended, but is useful if /// you want to add random user strings. /// public USHeap USHeap { get { return usHeap; } } /// /// Gets the #GUID heap. Access to this heap is not recommended, but is useful if you /// want to add random GUIDs. /// public GuidHeap GuidHeap { get { return guidHeap; } } /// /// Gets the #Blob heap. Access to this heap is not recommended, but is useful if you /// want to add random blobs. /// public BlobHeap BlobHeap { get { return blobHeap; } } /// /// Gets the #Pdb heap. It's only used if it's portable PDB metadata /// public PdbHeap PdbHeap { get { return pdbHeap; } } /// /// Gets all exported methods /// public List ExportedMethods { get { return exportedMethods; } } /// /// The public key that should be used instead of the one in . /// internal byte[] AssemblyPublicKey { get; set; } internal sealed class SortedRows where T : class where TRow : class { public List infos = new List(); Dictionary toRid = new Dictionary(); bool isSorted; public struct Info { public T data; public TRow row; public Info(T data, TRow row) { this.data = data; this.row = row; } } public void Add(T data, TRow row) { if (isSorted) throw new ModuleWriterException(string.Format("Adding a row after it's been sorted. Table: {0}", row.GetType())); infos.Add(new Info(data, row)); toRid[data] = (uint)toRid.Count + 1; } public void Sort(Comparison comparison) { infos.Sort(CreateComparison(comparison)); toRid.Clear(); for (int i = 0; i < infos.Count; i++) toRid[infos[i].data] = (uint)i + 1; isSorted = true; } Comparison CreateComparison(Comparison comparison) { return (a, b) => { int c = comparison(a, b); if (c != 0) return c; // Make sure it's a stable sort return toRid[a.data].CompareTo(toRid[b.data]); }; } public uint Rid(T data) { return toRid[data]; } public bool TryGetRid(T data, out uint rid) { if (data == null) { rid = 0; return false; } return toRid.TryGetValue(data, out rid); } } internal sealed class Rows where T : class { Dictionary dict = new Dictionary(); public int Count { get { return dict.Count; } } public bool TryGetRid(T value, out uint rid) { if (value == null) { rid = 0; return false; } return dict.TryGetValue(value, out rid); } public bool Exists(T value) { return dict.ContainsKey(value); } public void Add(T value, uint rid) { dict.Add(value, rid); } public uint Rid(T value) { return dict[value]; } public void SetRid(T value, uint rid) { dict[value] = rid; } } /// /// Creates a instance /// /// Module /// Constants list /// Method bodies list /// .NET resources list /// Options /// Debug metadata kind /// A new instance public static MetaData Create(ModuleDef module, UniqueChunkList constants, MethodBodyChunks methodBodies, NetResources netResources, MetaDataOptions options = null, DebugMetaDataKind debugKind = DebugMetaDataKind.None) { if (options == null) options = new MetaDataOptions(); if ((options.Flags & MetaDataFlags.PreserveRids) != 0 && module is ModuleDefMD) return new PreserveTokensMetaData(module, constants, methodBodies, netResources, options, debugKind, false); return new NormalMetaData(module, constants, methodBodies, netResources, options, debugKind, false); } /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Gets the bit /// public bool PreserveTypeRefRids { get { return (options.Flags & MetaDataFlags.PreserveTypeRefRids) != 0; } } /// /// Gets the bit /// public bool PreserveTypeDefRids { get { return (options.Flags & MetaDataFlags.PreserveTypeDefRids) != 0; } } /// /// Gets the bit /// public bool PreserveFieldRids { get { return (options.Flags & MetaDataFlags.PreserveFieldRids) != 0; } } /// /// Gets the bit /// public bool PreserveMethodRids { get { return (options.Flags & MetaDataFlags.PreserveMethodRids) != 0; } } /// /// Gets the bit /// public bool PreserveParamRids { get { return (options.Flags & MetaDataFlags.PreserveParamRids) != 0; } } /// /// Gets the bit /// public bool PreserveMemberRefRids { get { return (options.Flags & MetaDataFlags.PreserveMemberRefRids) != 0; } } /// /// Gets the bit /// public bool PreserveStandAloneSigRids { get { return (options.Flags & MetaDataFlags.PreserveStandAloneSigRids) != 0; } } /// /// Gets the bit /// public bool PreserveEventRids { get { return (options.Flags & MetaDataFlags.PreserveEventRids) != 0; } } /// /// Gets the bit /// public bool PreservePropertyRids { get { return (options.Flags & MetaDataFlags.PreservePropertyRids) != 0; } } /// /// Gets the bit /// public bool PreserveTypeSpecRids { get { return (options.Flags & MetaDataFlags.PreserveTypeSpecRids) != 0; } } /// /// Gets the bit /// public bool PreserveMethodSpecRids { get { return (options.Flags & MetaDataFlags.PreserveMethodSpecRids) != 0; } } /// /// Gets/sets the bit /// public bool PreserveStringsOffsets { get { return (options.Flags & MetaDataFlags.PreserveStringsOffsets) != 0; } set { if (value) options.Flags |= MetaDataFlags.PreserveStringsOffsets; else options.Flags &= ~MetaDataFlags.PreserveStringsOffsets; } } /// /// Gets/sets the bit /// public bool PreserveUSOffsets { get { return (options.Flags & MetaDataFlags.PreserveUSOffsets) != 0; } set { if (value) options.Flags |= MetaDataFlags.PreserveUSOffsets; else options.Flags &= ~MetaDataFlags.PreserveUSOffsets; } } /// /// Gets/sets the bit /// public bool PreserveBlobOffsets { get { return (options.Flags & MetaDataFlags.PreserveBlobOffsets) != 0; } set { if (value) options.Flags |= MetaDataFlags.PreserveBlobOffsets; else options.Flags &= ~MetaDataFlags.PreserveBlobOffsets; } } /// /// Gets/sets the bit /// public bool PreserveExtraSignatureData { get { return (options.Flags & MetaDataFlags.PreserveExtraSignatureData) != 0; } set { if (value) options.Flags |= MetaDataFlags.PreserveExtraSignatureData; else options.Flags &= ~MetaDataFlags.PreserveExtraSignatureData; } } /// /// Gets/sets the bit /// public bool KeepOldMaxStack { get { return (options.Flags & MetaDataFlags.KeepOldMaxStack) != 0; } set { if (value) options.Flags |= MetaDataFlags.KeepOldMaxStack; else options.Flags &= ~MetaDataFlags.KeepOldMaxStack; } } /// /// Gets/sets the bit /// public bool AlwaysCreateGuidHeap { get { return (options.Flags & MetaDataFlags.AlwaysCreateGuidHeap) != 0; } set { if (value) options.Flags |= MetaDataFlags.AlwaysCreateGuidHeap; else options.Flags &= ~MetaDataFlags.AlwaysCreateGuidHeap; } } /// /// Gets/sets the bit /// public bool AlwaysCreateStringsHeap { get { return (options.Flags & MetaDataFlags.AlwaysCreateStringsHeap) != 0; } set { if (value) options.Flags |= MetaDataFlags.AlwaysCreateStringsHeap; else options.Flags &= ~MetaDataFlags.AlwaysCreateStringsHeap; } } /// /// Gets/sets the bit /// public bool AlwaysCreateUSHeap { get { return (options.Flags & MetaDataFlags.AlwaysCreateUSHeap) != 0; } set { if (value) options.Flags |= MetaDataFlags.AlwaysCreateUSHeap; else options.Flags &= ~MetaDataFlags.AlwaysCreateUSHeap; } } /// /// Gets/sets the bit /// public bool AlwaysCreateBlobHeap { get { return (options.Flags & MetaDataFlags.AlwaysCreateBlobHeap) != 0; } set { if (value) options.Flags |= MetaDataFlags.AlwaysCreateBlobHeap; else options.Flags &= ~MetaDataFlags.AlwaysCreateBlobHeap; } } /// /// Gets/sets the bit /// public bool RoslynSortInterfaceImpl { get { return (options.Flags & MetaDataFlags.RoslynSortInterfaceImpl) != 0; } set { if (value) options.Flags |= MetaDataFlags.RoslynSortInterfaceImpl; else options.Flags &= ~MetaDataFlags.RoslynSortInterfaceImpl; } } /// /// If true, use the original Field RVAs. If it has no RVA, assume it's a new /// field value and create a new Field RVA. /// internal bool KeepFieldRVA { get; set; } /// /// Gets the number of methods that will be written. /// protected abstract int NumberOfMethods { get; } internal MetaData(ModuleDef module, UniqueChunkList constants, MethodBodyChunks methodBodies, NetResources netResources, MetaDataOptions options, DebugMetaDataKind debugKind, bool isStandaloneDebugMetadata) { this.module = module; this.constants = constants; this.methodBodies = methodBodies; this.netResources = netResources; this.options = options ?? new MetaDataOptions(); this.metaDataHeader = new MetaDataHeader(isStandaloneDebugMetadata ? this.options.DebugMetaDataHeaderOptions : this.options.MetaDataHeaderOptions); this.tablesHeap = new TablesHeap(this, isStandaloneDebugMetadata ? this.options.DebugTablesHeapOptions : this.options.TablesHeapOptions); this.stringsHeap = new StringsHeap(); this.usHeap = new USHeap(); this.guidHeap = new GuidHeap(); this.blobHeap = new BlobHeap(); this.pdbHeap = new PdbHeap(); this.isStandaloneDebugMetadata = isStandaloneDebugMetadata; switch (debugKind) { case DebugMetaDataKind.None: break; case DebugMetaDataKind.Standalone: Debug.Assert(!isStandaloneDebugMetadata); //TODO: Refactor this into a smaller class debugMetaData = new NormalMetaData(module, constants, methodBodies, netResources, options, DebugMetaDataKind.None, true); break; default: throw new ArgumentOutOfRangeException("debugKind"); } } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(ModuleDef module) { uint rid; moduleDefInfos.TryGetRid(module, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public abstract uint GetRid(TypeRef tr); /// /// Gets the new rid /// /// Value /// Its new rid or 0 public abstract uint GetRid(TypeDef td); /// /// Gets the new rid /// /// Value /// Its new rid or 0 public abstract uint GetRid(FieldDef fd); /// /// Gets the new rid /// /// Value /// Its new rid or 0 public abstract uint GetRid(MethodDef md); /// /// Gets the new rid /// /// Value /// Its new rid or 0 public abstract uint GetRid(ParamDef pd); /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(InterfaceImpl ii) { uint rid; interfaceImplInfos.TryGetRid(ii, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public abstract uint GetRid(MemberRef mr); /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetConstantRid(IHasConstant hc) { uint rid; hasConstantInfos.TryGetRid(hc, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetCustomAttributeRid(CustomAttribute ca) { uint rid; customAttributeInfos.TryGetRid(ca, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetFieldMarshalRid(IHasFieldMarshal hfm) { uint rid; fieldMarshalInfos.TryGetRid(hfm, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(DeclSecurity ds) { uint rid; declSecurityInfos.TryGetRid(ds, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetClassLayoutRid(TypeDef td) { uint rid; classLayoutInfos.TryGetRid(td, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetFieldLayoutRid(FieldDef fd) { uint rid; fieldLayoutInfos.TryGetRid(fd, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public abstract uint GetRid(StandAloneSig sas); /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetEventMapRid(TypeDef td) { uint rid; eventMapInfos.TryGetRid(td, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public abstract uint GetRid(EventDef ed); /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetPropertyMapRid(TypeDef td) { uint rid; propertyMapInfos.TryGetRid(td, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public abstract uint GetRid(PropertyDef pd); /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetMethodSemanticsRid(MethodDef md) { uint rid; methodSemanticsInfos.TryGetRid(md, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(ModuleRef mr) { uint rid; moduleRefInfos.TryGetRid(mr, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public abstract uint GetRid(TypeSpec ts); /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetImplMapRid(IMemberForwarded mf) { uint rid; implMapInfos.TryGetRid(mf, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetFieldRVARid(FieldDef fd) { uint rid; fieldRVAInfos.TryGetRid(fd, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(AssemblyDef asm) { uint rid; assemblyInfos.TryGetRid(asm, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(AssemblyRef asmRef) { uint rid; assemblyRefInfos.TryGetRid(asmRef, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(FileDef fd) { uint rid; fileDefInfos.TryGetRid(fd, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(ExportedType et) { uint rid; exportedTypeInfos.TryGetRid(et, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetManifestResourceRid(Resource resource) { uint rid; manifestResourceInfos.TryGetRid(resource, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetNestedClassRid(TypeDef td) { uint rid; nestedClassInfos.TryGetRid(td, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(GenericParam gp) { uint rid; genericParamInfos.TryGetRid(gp, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public abstract uint GetRid(MethodSpec ms); /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(GenericParamConstraint gpc) { uint rid; genericParamConstraintInfos.TryGetRid(gpc, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(PdbDocument doc) { if (debugMetaData == null) return 0; uint rid; debugMetaData.pdbDocumentInfos.TryGetRid(doc, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(PdbScope scope) { if (debugMetaData == null) return 0; uint rid; debugMetaData.localScopeInfos.TryGetRid(scope, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(PdbLocal local) { if (debugMetaData == null) return 0; uint rid; debugMetaData.localVariableInfos.TryGetRid(local, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(PdbConstant constant) { if (debugMetaData == null) return 0; uint rid; debugMetaData.localConstantInfos.TryGetRid(constant, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetRid(PdbImportScope importScope) { if (debugMetaData == null) return 0; uint rid; debugMetaData.importScopeInfos.TryGetRid(importScope, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetStateMachineMethodRid(PdbAsyncMethodCustomDebugInfo asyncMethod) { if (debugMetaData == null) return 0; uint rid; debugMetaData.stateMachineMethodInfos.TryGetRid(asyncMethod, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetStateMachineMethodRid(PdbIteratorMethodCustomDebugInfo iteratorMethod) { if (debugMetaData == null) return 0; uint rid; debugMetaData.stateMachineMethodInfos.TryGetRid(iteratorMethod, out rid); return rid; } /// /// Gets the new rid /// /// Value /// Its new rid or 0 public uint GetCustomDebugInfoRid(PdbCustomDebugInfo cdi) { if (debugMetaData == null) return 0; uint rid; debugMetaData.customDebugInfos.TryGetRid(cdi, out rid); return rid; } /// /// Gets the /// /// Method /// The or null if is /// null or not a method defined in this module. public MethodBody GetMethodBody(MethodDef md) { if (md == null) return null; MethodBody mb; methodToBody.TryGetValue(md, out mb); return mb; } /// /// Gets a method's local variable signature token /// /// Method /// Locals sig token or 0 public uint GetLocalVarSigToken(MethodDef md) { var mb = GetMethodBody(md); return mb == null ? 0 : mb.LocalVarSigTok; } /// /// Gets the where the resource data will be stored /// /// Embedded resource /// A instance or null if /// is invalid public ByteArrayChunk GetChunk(EmbeddedResource er) { if (er == null) return null; ByteArrayChunk chunk; embeddedResourceToByteArray.TryGetValue(er, out chunk); return chunk; } /// /// Gets the where the initial value is stored /// /// Field /// A instance or null if /// is invalid public ByteArrayChunk GetInitialValueChunk(FieldDef fd) { if (fd == null) return null; ByteArrayChunk chunk; fieldToInitialValue.TryGetValue(fd, out chunk); return chunk; } ILogger GetLogger() { return logger ?? DummyLogger.ThrowModuleWriterExceptionOnErrorInstance; } /// /// Called when an error is detected /// /// Error message /// Optional message arguments protected void Error(string message, params object[] args) { GetLogger().Log(this, LoggerEvent.Error, message, args); } /// /// Called to warn of something /// /// Warning message /// Optional message arguments protected void Warning(string message, params object[] args) { GetLogger().Log(this, LoggerEvent.Warning, message, args); } /// /// Creates the .NET metadata tables /// public void CreateTables() { Listener.OnMetaDataEvent(this, MetaDataEvent.BeginCreateTables); if (module.Types.Count == 0 || module.Types[0] == null) throw new ModuleWriterException("Missing global type"); var moduleDefMD = module as ModuleDefMD; if (moduleDefMD != null) { if (PreserveStringsOffsets) stringsHeap.Populate(moduleDefMD.StringsStream); if (PreserveUSOffsets) usHeap.Populate(moduleDefMD.USStream); if (PreserveBlobOffsets) blobHeap.Populate(moduleDefMD.BlobStream); } Create(); } /// /// Updates each Method row's RVA column if it has any code /// void UpdateMethodRvas() { foreach (var kv in methodToBody) { var method = kv.Key; var body = kv.Value; var row = tablesHeap.MethodTable[GetRid(method)]; row.RVA = (uint)body.RVA; } foreach (var kv in methodToNativeBody) { var method = kv.Key; var body = kv.Value; var row = tablesHeap.MethodTable[GetRid(method)]; row.RVA = (uint)body.RVA; } } /// /// Updates the FieldRVA rows /// void UpdateFieldRvas() { foreach (var kv in fieldToInitialValue) { var field = kv.Key; var iv = kv.Value; var row = tablesHeap.FieldRVATable[fieldRVAInfos.Rid(field)]; row.RVA = (uint)iv.RVA; } } void Create() { Debug.Assert(!isStandaloneDebugMetadata); Initialize(); allTypeDefs = GetAllTypeDefs(); Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateTypeDefRids); AllocateTypeDefRids(); Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids); AllocateMemberDefRids(); Listener.OnMetaDataEvent(this, MetaDataEvent.MemberDefRidsAllocated); AddModule(module); AddPdbDocuments(); InitializeMethodDebugInformation(); InitializeTypeDefsAndMemberDefs(); Listener.OnMetaDataEvent(this, MetaDataEvent.MemberDefsInitialized); InitializeVTableFixups(); AddExportedTypes(); InitializeEntryPoint(); if (module.Assembly != null) AddAssembly(module.Assembly, AssemblyPublicKey); Listener.OnMetaDataEvent(this, MetaDataEvent.BeforeSortTables); SortTables(); InitializeGenericParamConstraintTable(); Listener.OnMetaDataEvent(this, MetaDataEvent.MostTablesSorted); WriteTypeDefAndMemberDefCustomAttributesAndCustomDebugInfos(); Listener.OnMetaDataEvent(this, MetaDataEvent.MemberDefCustomAttributesWritten); Listener.OnMetaDataEvent(this, MetaDataEvent.BeginAddResources); AddResources(module.Resources); Listener.OnMetaDataEvent(this, MetaDataEvent.EndAddResources); Listener.OnMetaDataEvent(this, MetaDataEvent.BeginWriteMethodBodies); WriteMethodBodies(); Listener.OnMetaDataEvent(this, MetaDataEvent.EndWriteMethodBodies); BeforeSortingCustomAttributes(); InitializeCustomAttributeAndCustomDebugInfoTables(); Listener.OnMetaDataEvent(this, MetaDataEvent.OnAllTablesSorted); EverythingInitialized(); Listener.OnMetaDataEvent(this, MetaDataEvent.EndCreateTables); } /// /// Initializes all TypeDef, Field, Method, Event, /// Property and Param rows. Other tables that are related to these six /// tables are also updated. No custom attributes are written yet, though. Method bodies /// aren't written either. /// void InitializeTypeDefsAndMemberDefs() { int numTypes = allTypeDefs.Count; int typeNum = 0; int notifyNum = 0; const int numNotifyEvents = 5; // InitializeTypeDefsAndMemberDefs0 - InitializeTypeDefsAndMemberDefs4 int notifyAfter = numTypes / numNotifyEvents; foreach (var type in allTypeDefs) { if (typeNum++ == notifyAfter && notifyNum < numNotifyEvents) { Listener.OnMetaDataEvent(this, MetaDataEvent.InitializeTypeDefsAndMemberDefs0 + notifyNum++); notifyAfter += numTypes / numNotifyEvents; } if (type == null) { Error("TypeDef is null"); continue; } uint typeRid = GetRid(type); var typeRow = tablesHeap.TypeDefTable[typeRid]; typeRow.Flags = (uint)type.Attributes; typeRow.Name = stringsHeap.Add(type.Name); typeRow.Namespace = stringsHeap.Add(type.Namespace); typeRow.Extends = type.BaseType == null ? 0 : AddTypeDefOrRef(type.BaseType); AddGenericParams(new MDToken(Table.TypeDef, typeRid), type.GenericParameters); AddDeclSecurities(new MDToken(Table.TypeDef, typeRid), type.DeclSecurities); AddInterfaceImpls(typeRid, type.Interfaces); AddClassLayout(type); AddNestedType(type, type.DeclaringType); foreach (var field in type.Fields) { if (field == null) { Error("Field is null. TypeDef {0} ({1:X8})", type, type.MDToken.Raw); continue; } uint rid = GetRid(field); var row = tablesHeap.FieldTable[rid]; row.Flags = (ushort)field.Attributes; row.Name = stringsHeap.Add(field.Name); row.Signature = GetSignature(field.Signature); AddFieldLayout(field); AddFieldMarshal(new MDToken(Table.Field, rid), field); AddFieldRVA(field); AddImplMap(new MDToken(Table.Field, rid), field); AddConstant(new MDToken(Table.Field, rid), field); } foreach (var method in type.Methods) { if (method == null) { Error("Method is null. TypeDef {0} ({1:X8})", type, type.MDToken.Raw); continue; } if (method.ExportInfo != null) ExportedMethods.Add(method); uint rid = GetRid(method); var row = tablesHeap.MethodTable[rid]; row.ImplFlags = (ushort)method.ImplAttributes; row.Flags = (ushort)method.Attributes; row.Name = stringsHeap.Add(method.Name); row.Signature = GetSignature(method.Signature); AddGenericParams(new MDToken(Table.Method, rid), method.GenericParameters); AddDeclSecurities(new MDToken(Table.Method, rid), method.DeclSecurities); AddImplMap(new MDToken(Table.Method, rid), method); AddMethodImpls(method, method.Overrides); foreach (var pd in method.ParamDefs) { if (pd == null) { Error("Param is null. Method {0} ({1:X8})", method, method.MDToken.Raw); continue; } uint pdRid = GetRid(pd); var pdRow = tablesHeap.ParamTable[pdRid]; pdRow.Flags = (ushort)pd.Attributes; pdRow.Sequence = pd.Sequence; pdRow.Name = stringsHeap.Add(pd.Name); AddConstant(new MDToken(Table.Param, pdRid), pd); AddFieldMarshal(new MDToken(Table.Param, pdRid), pd); } } if (!IsEmpty(type.Events)) { foreach (var evt in type.Events) { if (evt == null) { Error("Event is null. TypeDef {0} ({1:X8})", type, type.MDToken.Raw); continue; } uint rid = GetRid(evt); var row = tablesHeap.EventTable[rid]; row.EventFlags = (ushort)evt.Attributes; row.Name = stringsHeap.Add(evt.Name); row.EventType = AddTypeDefOrRef(evt.EventType); AddMethodSemantics(evt); } } if (!IsEmpty(type.Properties)) { foreach (var prop in type.Properties) { if (prop == null) { Error("Property is null. TypeDef {0} ({1:X8})", type, type.MDToken.Raw); continue; } uint rid = GetRid(prop); var row = tablesHeap.PropertyTable[rid]; row.PropFlags = (ushort)prop.Attributes; row.Name = stringsHeap.Add(prop.Name); row.Type = GetSignature(prop.Type); AddConstant(new MDToken(Table.Property, rid), prop); AddMethodSemantics(prop); } } } while (notifyNum < numNotifyEvents) Listener.OnMetaDataEvent(this, MetaDataEvent.InitializeTypeDefsAndMemberDefs0 + notifyNum++); } /// /// Writes TypeDef, Field, Method, Event, /// Property and Param custom attributes and custom debug infos. /// void WriteTypeDefAndMemberDefCustomAttributesAndCustomDebugInfos() { int numTypes = allTypeDefs.Count; int typeNum = 0; int notifyNum = 0; const int numNotifyEvents = 5; // WriteTypeDefAndMemberDefCustomAttributes0 - WriteTypeDefAndMemberDefCustomAttributes4 int notifyAfter = numTypes / numNotifyEvents; uint rid; foreach (var type in allTypeDefs) { if (typeNum++ == notifyAfter && notifyNum < numNotifyEvents) { Listener.OnMetaDataEvent(this, MetaDataEvent.WriteTypeDefAndMemberDefCustomAttributes0 + notifyNum++); notifyAfter += numTypes / numNotifyEvents; } if (type == null) continue; rid = GetRid(type); AddCustomAttributes(Table.TypeDef, rid, type); AddCustomDebugInformationList(Table.TypeDef, rid, type); foreach (var field in type.Fields) { if (field == null) continue; rid = GetRid(field); AddCustomAttributes(Table.Field, rid, field); AddCustomDebugInformationList(Table.Field, rid, field); } foreach (var method in type.Methods) { if (method == null) continue; AddCustomAttributes(Table.Method, GetRid(method), method); // Method custom debug info is added later when writing method bodies foreach (var pd in method.ParamDefs) { if (pd == null) continue; rid = GetRid(pd); AddCustomAttributes(Table.Param, rid, pd); AddCustomDebugInformationList(Table.Param, rid, pd); } } foreach (var evt in type.Events) { if (evt == null) continue; rid = GetRid(evt); AddCustomAttributes(Table.Event, rid, evt); AddCustomDebugInformationList(Table.Event, rid, evt); } foreach (var prop in type.Properties) { if (prop == null) continue; rid = GetRid(prop); AddCustomAttributes(Table.Property, rid, prop); AddCustomDebugInformationList(Table.Property, rid, prop); } } while (notifyNum < numNotifyEvents) Listener.OnMetaDataEvent(this, MetaDataEvent.WriteTypeDefAndMemberDefCustomAttributes0 + notifyNum++); } /// /// Adds the tokens of all methods in all vtables, if any /// void InitializeVTableFixups() { var fixups = module.VTableFixups; if (fixups == null || fixups.VTables.Count == 0) return; foreach (var vtable in fixups) { if (vtable == null) { Error("VTable is null"); continue; } foreach (var method in vtable) { if (method == null) continue; AddMDTokenProvider(method); } } } void AddExportedTypes() { foreach (var et in module.ExportedTypes) AddExportedType(et); } /// /// Adds the entry point. It's only needed if it's a since if it's /// a , it will have already been added. /// void InitializeEntryPoint() { var epFile = module.ManagedEntryPoint as FileDef; if (epFile != null) AddFile(epFile); } /// /// Sorts all unsorted tables except GenericParamConstraint and CustomAttribute /// void SortTables() { classLayoutInfos.Sort((a, b) => a.row.Parent.CompareTo(b.row.Parent)); hasConstantInfos.Sort((a, b) => a.row.Parent.CompareTo(b.row.Parent)); declSecurityInfos.Sort((a, b) => a.row.Parent.CompareTo(b.row.Parent)); fieldLayoutInfos.Sort((a, b) => a.row.Field.CompareTo(b.row.Field)); fieldMarshalInfos.Sort((a, b) => a.row.Parent.CompareTo(b.row.Parent)); fieldRVAInfos.Sort((a, b) => a.row.Field.CompareTo(b.row.Field)); implMapInfos.Sort((a, b) => a.row.MemberForwarded.CompareTo(b.row.MemberForwarded)); methodImplInfos.Sort((a, b) => a.row.Class.CompareTo(b.row.Class)); methodSemanticsInfos.Sort((a, b)=> a.row.Association.CompareTo(b.row.Association)); nestedClassInfos.Sort((a, b) => a.row.NestedClass.CompareTo(b.row.NestedClass)); genericParamInfos.Sort((a, b) => { if (a.row.Owner != b.row.Owner) return a.row.Owner.CompareTo(b.row.Owner); return a.row.Number.CompareTo(b.row.Number); }); if (RoslynSortInterfaceImpl) interfaceImplInfos.Sort((a, b) => a.row.Class.CompareTo(b.row.Class)); else { interfaceImplInfos.Sort((a, b) => { if (a.row.Class != b.row.Class) return a.row.Class.CompareTo(b.row.Class); return a.row.Interface.CompareTo(b.row.Interface); }); } tablesHeap.ClassLayoutTable.IsSorted = true; tablesHeap.ConstantTable.IsSorted = true; tablesHeap.DeclSecurityTable.IsSorted = true; tablesHeap.FieldLayoutTable.IsSorted = true; tablesHeap.FieldMarshalTable.IsSorted = true; tablesHeap.FieldRVATable.IsSorted = true; tablesHeap.GenericParamTable.IsSorted = true; tablesHeap.ImplMapTable.IsSorted = true; tablesHeap.InterfaceImplTable.IsSorted = true; tablesHeap.MethodImplTable.IsSorted = true; tablesHeap.MethodSemanticsTable.IsSorted = true; tablesHeap.NestedClassTable.IsSorted = true; // These two are also sorted tablesHeap.EventMapTable.IsSorted = true; tablesHeap.PropertyMapTable.IsSorted = true; foreach (var info in classLayoutInfos.infos) tablesHeap.ClassLayoutTable.Create(info.row); foreach (var info in hasConstantInfos.infos) tablesHeap.ConstantTable.Create(info.row); foreach (var info in declSecurityInfos.infos) tablesHeap.DeclSecurityTable.Create(info.row); foreach (var info in fieldLayoutInfos.infos) tablesHeap.FieldLayoutTable.Create(info.row); foreach (var info in fieldMarshalInfos.infos) tablesHeap.FieldMarshalTable.Create(info.row); foreach (var info in fieldRVAInfos.infos) tablesHeap.FieldRVATable.Create(info.row); foreach (var info in genericParamInfos.infos) tablesHeap.GenericParamTable.Create(info.row); foreach (var info in implMapInfos.infos) tablesHeap.ImplMapTable.Create(info.row); foreach (var info in interfaceImplInfos.infos) tablesHeap.InterfaceImplTable.Create(info.row); foreach (var info in methodImplInfos.infos) tablesHeap.MethodImplTable.Create(info.row); foreach (var info in methodSemanticsInfos.infos) tablesHeap.MethodSemanticsTable.Create(info.row); foreach (var info in nestedClassInfos.infos) tablesHeap.NestedClassTable.Create(info.row); foreach (var info in interfaceImplInfos.infos) { uint rid = interfaceImplInfos.Rid(info.data); AddCustomAttributes(Table.InterfaceImpl, rid, info.data); AddCustomDebugInformationList(Table.InterfaceImpl, rid, info.data); } foreach (var info in declSecurityInfos.infos) { uint rid = declSecurityInfos.Rid(info.data); AddCustomAttributes(Table.DeclSecurity, rid, info.data); AddCustomDebugInformationList(Table.DeclSecurity, rid, info.data); } foreach (var info in genericParamInfos.infos) { uint rid = genericParamInfos.Rid(info.data); AddCustomAttributes(Table.GenericParam, rid, info.data); AddCustomDebugInformationList(Table.GenericParam, rid, info.data); } } /// /// Initializes the GenericParamConstraint table /// void InitializeGenericParamConstraintTable() { foreach (var type in allTypeDefs) { if (type == null) continue; AddGenericParamConstraints(type.GenericParameters); foreach (var method in type.Methods) { if (method == null) continue; AddGenericParamConstraints(method.GenericParameters); } } genericParamConstraintInfos.Sort((a, b) => a.row.Owner.CompareTo(b.row.Owner)); tablesHeap.GenericParamConstraintTable.IsSorted = true; foreach (var info in genericParamConstraintInfos.infos) tablesHeap.GenericParamConstraintTable.Create(info.row); foreach (var info in genericParamConstraintInfos.infos) { uint rid = genericParamConstraintInfos.Rid(info.data); AddCustomAttributes(Table.GenericParamConstraint, rid, info.data); AddCustomDebugInformationList(Table.GenericParamConstraint, rid, info.data); } } /// /// Inserts all custom attribute / custom debug info rows in the tables and sort them /// void InitializeCustomAttributeAndCustomDebugInfoTables() { customAttributeInfos.Sort((a, b) => a.row.Parent.CompareTo(b.row.Parent)); tablesHeap.CustomAttributeTable.IsSorted = true; foreach (var info in customAttributeInfos.infos) tablesHeap.CustomAttributeTable.Create(info.row); if (debugMetaData != null) { debugMetaData.stateMachineMethodInfos.Sort((a, b) => a.row.MoveNextMethod.CompareTo(b.row.MoveNextMethod)); debugMetaData.tablesHeap.StateMachineMethodTable.IsSorted = true; foreach (var info in debugMetaData.stateMachineMethodInfos.infos) debugMetaData.tablesHeap.StateMachineMethodTable.Create(info.row); debugMetaData.customDebugInfos.Sort((a, b) => a.row.Parent.CompareTo(b.row.Parent)); debugMetaData.tablesHeap.CustomDebugInformationTable.IsSorted = true; foreach (var info in debugMetaData.customDebugInfos.infos) debugMetaData.tablesHeap.CustomDebugInformationTable.Create(info.row); } } struct MethodScopeDebugInfo { public uint MethodRid; public PdbScope Scope; public uint ScopeStart; public uint ScopeLength; } /// /// Writes all method bodies /// void WriteMethodBodies() { Debug.Assert(!isStandaloneDebugMetadata); int numMethods = NumberOfMethods; int methodNum = 0; int notifyNum = 0; const int numNotifyEvents = 10; // WriteMethodBodies0 - WriteMethodBodies9 int notifyAfter = numMethods / numNotifyEvents; List methodScopeDebugInfos; List scopeStack; SerializerMethodContext serializerMethodContext; if (debugMetaData == null) { methodScopeDebugInfos = null; scopeStack = null; serializerMethodContext = null; } else { methodScopeDebugInfos = new List(); scopeStack = new List(); serializerMethodContext = AllocSerializerMethodContext(); } bool keepMaxStack = KeepOldMaxStack; var writer = new MethodBodyWriter(this); foreach (var type in allTypeDefs) { if (type == null) continue; foreach (var method in type.Methods) { if (method == null) continue; if (methodNum++ == notifyAfter && notifyNum < numNotifyEvents) { Listener.OnMetaDataEvent(this, MetaDataEvent.WriteMethodBodies0 + notifyNum++); notifyAfter += numMethods / numNotifyEvents; } uint localVarSigTok = 0; uint rid = GetRid(method); var cilBody = method.Body; if (cilBody != null) { if (!(cilBody.Instructions.Count == 0 && cilBody.Variables.Count == 0)) { writer.Reset(cilBody, keepMaxStack || cilBody.KeepOldMaxStack); writer.Write(); var mb = methodBodies.Add(new MethodBody(writer.Code, writer.ExtraSections, writer.LocalVarSigTok)); methodToBody[method] = mb; localVarSigTok = writer.LocalVarSigTok; } } else { var nativeBody = method.NativeBody; if (nativeBody != null) methodToNativeBody[method] = nativeBody; else if (method.MethodBody != null) Error("Unsupported method body"); } if (debugMetaData != null) { if (cilBody != null) { var pdbMethod = cilBody.PdbMethod; if (pdbMethod != null) { // We don't need to write empty scopes if (!IsEmptyRootScope(cilBody, pdbMethod.Scope)) { serializerMethodContext.SetBody(method); scopeStack.Add(pdbMethod.Scope); while (scopeStack.Count > 0) { var scope = scopeStack[scopeStack.Count - 1]; scopeStack.RemoveAt(scopeStack.Count - 1); scopeStack.AddRange(scope.Scopes); uint scopeStart = serializerMethodContext.GetOffset(scope.Start); uint scopeEnd = serializerMethodContext.GetOffset(scope.End); methodScopeDebugInfos.Add(new MethodScopeDebugInfo() { MethodRid = rid, Scope = scope, ScopeStart = scopeStart, ScopeLength = scopeEnd - scopeStart, }); } } } } } // Always add CDIs even if it has no managed method body AddCustomDebugInformationList(method, rid, localVarSigTok); } } if (debugMetaData != null) { methodScopeDebugInfos.Sort((a, b) => { int c = a.MethodRid.CompareTo(b.MethodRid); if (c != 0) return c; c = a.ScopeStart.CompareTo(b.ScopeStart); if (c != 0) return c; return b.ScopeLength.CompareTo(a.ScopeLength); }); foreach (var info in methodScopeDebugInfos) { var row = new RawLocalScopeRow(); debugMetaData.localScopeInfos.Add(info.Scope, row); uint localScopeRid = (uint)debugMetaData.localScopeInfos.infos.Count; row.Method = info.MethodRid; row.ImportScope = AddImportScope(info.Scope.ImportScope); row.VariableList = (uint)debugMetaData.tablesHeap.LocalVariableTable.Rows + 1; row.ConstantList = (uint)debugMetaData.tablesHeap.LocalConstantTable.Rows + 1; row.StartOffset = info.ScopeStart; row.Length = info.ScopeLength; foreach (var local in info.Scope.Variables) AddLocalVariable(local); foreach (var constant in info.Scope.Constants) AddLocalConstant(constant); AddCustomDebugInformationList(Table.LocalScope, localScopeRid, info.Scope.CustomDebugInfos); } debugMetaData.tablesHeap.LocalScopeTable.IsSorted = true; foreach (var info in debugMetaData.localScopeInfos.infos) debugMetaData.tablesHeap.LocalScopeTable.Create(info.row); } if (serializerMethodContext != null) Free(ref serializerMethodContext); while (notifyNum < numNotifyEvents) Listener.OnMetaDataEvent(this, MetaDataEvent.WriteMethodBodies0 + notifyNum++); } static bool IsEmptyRootScope(CilBody cilBody, PdbScope scope) { if (scope.Variables.Count != 0) return false; if (scope.Constants.Count != 0) return false; if (scope.Namespaces.Count != 0) return false; if (scope.ImportScope != null) return false; if (scope.Scopes.Count != 0) return false; if (scope.CustomDebugInfos.Count != 0) return false; if (scope.End != null) return false; if (cilBody.Instructions.Count != 0 && cilBody.Instructions[0] != scope.Start) return false; return true; } /// /// Checks whether a list is empty or whether it contains only nulls /// /// Any type /// The list /// true if the list is empty or if it contains only nulls, false otherwise protected static bool IsEmpty(IList list) where T : class { if (list == null) return true; foreach (var e in list) { if (e != null) return false; } return true; } /// public MDToken GetToken(object o) { var tp = o as IMDTokenProvider; if (tp != null) return new MDToken(tp.MDToken.Table, AddMDTokenProvider(tp)); var s = o as string; if (s != null) return new MDToken((Table)0x70, usHeap.Add(s)); var methodSig = o as MethodSig; if (methodSig != null) return new MDToken(Table.StandAloneSig, AddStandAloneSig(methodSig, methodSig.OriginalToken)); var fieldSig = o as FieldSig; if (fieldSig != null) return new MDToken(Table.StandAloneSig, AddStandAloneSig(fieldSig, 0)); if (o == null) Error("Instruction operand is null"); else Error("Invalid instruction operand"); return new MDToken((Table)0xFF, 0x00FFFFFF); } /// public virtual MDToken GetToken(IList locals, uint origToken) { if (locals == null || locals.Count == 0) return new MDToken((Table)0, 0); var row = new RawStandAloneSigRow(GetSignature(new LocalSig(locals, false))); uint rid = tablesHeap.StandAloneSigTable.Add(row); //TODO: Add custom attributes //TODO: Add custom debug infos return new MDToken(Table.StandAloneSig, rid); } /// /// Adds a /// /// Method signature /// Original StandAloneSig token or 0 if none /// Its new rid protected virtual uint AddStandAloneSig(MethodSig methodSig, uint origToken) { if (methodSig == null) { Error("StandAloneSig: MethodSig is null"); return 0; } var row = new RawStandAloneSigRow(GetSignature(methodSig)); uint rid = tablesHeap.StandAloneSigTable.Add(row); //TODO: Add custom attributes //TODO: Add custom debug infos return rid; } /// /// Adds a /// /// FIeld signature /// Original StandAloneSig token or 0 if none /// Its new rid protected virtual uint AddStandAloneSig(FieldSig fieldSig, uint origToken) { if (fieldSig == null) { Error("StandAloneSig: FieldSig is null"); return 0; } var row = new RawStandAloneSigRow(GetSignature(fieldSig)); uint rid = tablesHeap.StandAloneSigTable.Add(row); //TODO: Add custom attributes //TODO: Add custom debug infos return rid; } uint AddMDTokenProvider(IMDTokenProvider tp) { if (tp != null) { switch (tp.MDToken.Table) { case Table.Module: return AddModule((ModuleDef)tp); case Table.TypeRef: return AddTypeRef((TypeRef)tp); case Table.TypeDef: return GetRid((TypeDef)tp); case Table.Field: return GetRid((FieldDef)tp); case Table.Method: return GetRid((MethodDef)tp); case Table.Param: return GetRid((ParamDef)tp); case Table.MemberRef: return AddMemberRef((MemberRef)tp); case Table.StandAloneSig: return AddStandAloneSig((StandAloneSig)tp); case Table.Event: return GetRid((EventDef)tp); case Table.Property: return GetRid((PropertyDef)tp); case Table.ModuleRef: return AddModuleRef((ModuleRef)tp); case Table.TypeSpec: return AddTypeSpec((TypeSpec)tp); case Table.Assembly: return AddAssembly((AssemblyDef)tp, null); case Table.AssemblyRef: return AddAssemblyRef((AssemblyRef)tp); case Table.File: return AddFile((FileDef)tp); case Table.ExportedType: return AddExportedType((ExportedType)tp); case Table.MethodSpec: return AddMethodSpec((MethodSpec)tp); case Table.FieldPtr: case Table.MethodPtr: case Table.ParamPtr: case Table.InterfaceImpl: case Table.Constant: case Table.CustomAttribute: case Table.FieldMarshal: case Table.DeclSecurity: case Table.ClassLayout: case Table.FieldLayout: case Table.EventMap: case Table.EventPtr: case Table.PropertyMap: case Table.PropertyPtr: case Table.MethodSemantics: case Table.MethodImpl: case Table.ImplMap: case Table.FieldRVA: case Table.ENCLog: case Table.ENCMap: case Table.AssemblyProcessor: case Table.AssemblyOS: case Table.AssemblyRefProcessor: case Table.AssemblyRefOS: case Table.ManifestResource: case Table.NestedClass: case Table.GenericParam: case Table.GenericParamConstraint: case Table.Document: case Table.MethodDebugInformation: case Table.LocalScope: case Table.LocalVariable: case Table.LocalConstant: case Table.ImportScope: case Table.StateMachineMethod: case Table.CustomDebugInformation: default: break; } } if (tp == null) Error("IMDTokenProvider is null"); else Error("Invalid IMDTokenProvider"); return 0; } /// /// Adds a /// /// Value /// Its encoded token protected uint AddTypeDefOrRef(ITypeDefOrRef tdr) { if (tdr == null) { Error("TypeDefOrRef is null"); return 0; } var token = new MDToken(tdr.MDToken.Table, AddMDTokenProvider(tdr)); uint encodedToken; if (!CodedToken.TypeDefOrRef.Encode(token, out encodedToken)) { Error("Can't encode TypeDefOrRef token {0:X8}", token.Raw); encodedToken = 0; } return encodedToken; } /// /// Adds a /// /// Value /// Its encoded token protected uint AddResolutionScope(IResolutionScope rs) { if (rs == null) { Error("ResolutionScope is null"); return 0; } var token = new MDToken(rs.MDToken.Table, AddMDTokenProvider(rs)); uint encodedToken; if (!CodedToken.ResolutionScope.Encode(token, out encodedToken)) { Error("Can't encode ResolutionScope token {0:X8}", token.Raw); encodedToken = 0; } return encodedToken; } /// /// Adds a /// /// Value /// Its encoded token protected uint AddMethodDefOrRef(IMethodDefOrRef mdr) { if (mdr == null) { Error("MethodDefOrRef is null"); return 0; } var token = new MDToken(mdr.MDToken.Table, AddMDTokenProvider(mdr)); uint encodedToken; if (!CodedToken.MethodDefOrRef.Encode(token, out encodedToken)) { Error("Can't encode MethodDefOrRef token {0:X8}", token.Raw); encodedToken = 0; } return encodedToken; } /// /// Adds a /// /// Value /// Its encoded token protected uint AddMemberRefParent(IMemberRefParent parent) { if (parent == null) { Error("MemberRefParent is null"); return 0; } var token = new MDToken(parent.MDToken.Table, AddMDTokenProvider(parent)); uint encodedToken; if (!CodedToken.MemberRefParent.Encode(token, out encodedToken)) { Error("Can't encode MemberRefParent token {0:X8}", token.Raw); encodedToken = 0; } return encodedToken; } /// /// Adds a /// /// Value /// Its encoded token protected uint AddImplementation(IImplementation impl) { if (impl == null) { Error("Implementation is null"); return 0; } var token = new MDToken(impl.MDToken.Table, AddMDTokenProvider(impl)); uint encodedToken; if (!CodedToken.Implementation.Encode(token, out encodedToken)) { Error("Can't encode Implementation token {0:X8}", token.Raw); encodedToken = 0; } return encodedToken; } /// /// Adds a /// /// Value /// Its encoded token protected uint AddCustomAttributeType(ICustomAttributeType cat) { if (cat == null) { Error("CustomAttributeType is null"); return 0; } var token = new MDToken(cat.MDToken.Table, AddMDTokenProvider(cat)); uint encodedToken; if (!CodedToken.CustomAttributeType.Encode(token, out encodedToken)) { Error("Can't encode CustomAttributeType token {0:X8}", token.Raw); encodedToken = 0; } return encodedToken; } /// /// Adds a NestedType row /// /// Nested type /// Declaring type protected void AddNestedType(TypeDef nestedType, TypeDef declaringType) { if (nestedType == null || declaringType == null) return; uint nestedRid = GetRid(nestedType); uint dtRid = GetRid(declaringType); if (nestedRid == 0 || dtRid == 0) return; var row = new RawNestedClassRow(nestedRid, dtRid); nestedClassInfos.Add(declaringType, row); } /// /// Adds a Module row /// /// Module /// Its new rid protected uint AddModule(ModuleDef module) { if (module == null) { Error("Module is null"); return 0; } if (this.module != module) Error("Module {0} must be referenced with a ModuleRef, not a ModuleDef", module); uint rid; if (moduleDefInfos.TryGetRid(module, out rid)) return rid; var row = new RawModuleRow(module.Generation, stringsHeap.Add(module.Name), guidHeap.Add(module.Mvid), guidHeap.Add(module.EncId), guidHeap.Add(module.EncBaseId)); rid = tablesHeap.ModuleTable.Add(row); moduleDefInfos.Add(module, rid); AddCustomAttributes(Table.Module, rid, module); AddCustomDebugInformationList(Table.Module, rid, module); return rid; } /// /// Adds a ModuleRef row /// /// Module ref /// Its new rid protected uint AddModuleRef(ModuleRef modRef) { if (modRef == null) { Error("ModuleRef is null"); return 0; } uint rid; if (moduleRefInfos.TryGetRid(modRef, out rid)) return rid; var row = new RawModuleRefRow(stringsHeap.Add(modRef.Name)); rid = tablesHeap.ModuleRefTable.Add(row); moduleRefInfos.Add(modRef, rid); AddCustomAttributes(Table.ModuleRef, rid, modRef); AddCustomDebugInformationList(Table.ModuleRef, rid, modRef); return rid; } /// /// Adds an AssemblyRef row /// /// Assembly ref /// Its new rid protected uint AddAssemblyRef(AssemblyRef asmRef) { if (asmRef == null) { Error("AssemblyRef is null"); return 0; } uint rid; if (assemblyRefInfos.TryGetRid(asmRef, out rid)) return rid; var version = Utils.CreateVersionWithNoUndefinedValues(asmRef.Version); var row = new RawAssemblyRefRow((ushort)version.Major, (ushort)version.Minor, (ushort)version.Build, (ushort)version.Revision, (uint)asmRef.Attributes, blobHeap.Add(PublicKeyBase.GetRawData(asmRef.PublicKeyOrToken)), stringsHeap.Add(asmRef.Name), stringsHeap.Add(asmRef.Culture), blobHeap.Add(asmRef.Hash)); rid = tablesHeap.AssemblyRefTable.Add(row); assemblyRefInfos.Add(asmRef, rid); AddCustomAttributes(Table.AssemblyRef, rid, asmRef); AddCustomDebugInformationList(Table.AssemblyRef, rid, asmRef); return rid; } /// /// Adds an Assembly row /// /// Assembly /// The public key that should be used /// Its new rid protected uint AddAssembly(AssemblyDef asm, byte[] publicKey) { if (asm == null) { Error("Assembly is null"); return 0; } uint rid; if (assemblyInfos.TryGetRid(asm, out rid)) return rid; var asmAttrs = asm.Attributes; if (publicKey != null) asmAttrs |= AssemblyAttributes.PublicKey; else publicKey = PublicKeyBase.GetRawData(asm.PublicKeyOrToken); var version = Utils.CreateVersionWithNoUndefinedValues(asm.Version); var row = new RawAssemblyRow((uint)asm.HashAlgorithm, (ushort)version.Major, (ushort)version.Minor, (ushort)version.Build, (ushort)version.Revision, (uint)asmAttrs, blobHeap.Add(publicKey), stringsHeap.Add(asm.Name), stringsHeap.Add(asm.Culture)); rid = tablesHeap.AssemblyTable.Add(row); assemblyInfos.Add(asm, rid); AddDeclSecurities(new MDToken(Table.Assembly, rid), asm.DeclSecurities); AddCustomAttributes(Table.Assembly, rid, asm); AddCustomDebugInformationList(Table.Assembly, rid, asm); return rid; } /// /// Adds generic parameters /// /// New token of owner /// All generic params protected void AddGenericParams(MDToken token, IList gps) { if (gps == null) return; foreach (var gp in gps) AddGenericParam(token, gp); } /// /// Adds a generic param /// /// New token of owner /// Generic paramater protected void AddGenericParam(MDToken owner, GenericParam gp) { if (gp == null) { Error("GenericParam is null"); return; } uint encodedOwner; if (!CodedToken.TypeOrMethodDef.Encode(owner, out encodedOwner)) { Error("Can't encode TypeOrMethodDef token {0:X8}", owner.Raw); encodedOwner = 0; } var row = new RawGenericParamRow(gp.Number, (ushort)gp.Flags, encodedOwner, stringsHeap.Add(gp.Name), gp.Kind == null ? 0 : AddTypeDefOrRef(gp.Kind)); genericParamInfos.Add(gp, row); } void AddGenericParamConstraints(IList gps) { if (gps == null) return; foreach (var gp in gps) { if (gp == null) continue; uint rid = genericParamInfos.Rid(gp); AddGenericParamConstraints(rid, gp.GenericParamConstraints); } } /// /// Adds generic parameter constraints /// /// New rid of owner generic param /// Its constraints protected void AddGenericParamConstraints(uint gpRid, IList constraints) { if (constraints == null) return; foreach (var gpc in constraints) AddGenericParamConstraint(gpRid, gpc); } /// /// Adds a generic parameter constraint /// /// New rid of owner generic param /// Generic parameter constraint protected void AddGenericParamConstraint(uint gpRid, GenericParamConstraint gpc) { if (gpc == null) { Error("GenericParamConstraint is null"); return; } var row = new RawGenericParamConstraintRow(gpRid, AddTypeDefOrRef(gpc.Constraint)); genericParamConstraintInfos.Add(gpc, row); } /// /// Adds a InterfaceImpl row /// /// New rid of owner /// All interfaces protected void AddInterfaceImpls(uint typeDefRid, IList ifaces) { foreach (var iface in ifaces) { if (iface == null) continue; var row = new RawInterfaceImplRow(typeDefRid, AddTypeDefOrRef(iface.Interface)); interfaceImplInfos.Add(iface, row); } } /// /// Adds a FieldLayout row /// /// Owner field protected void AddFieldLayout(FieldDef field) { if (field == null || field.FieldOffset == null) return; var rid = GetRid(field); var row = new RawFieldLayoutRow(field.FieldOffset.Value, rid); fieldLayoutInfos.Add(field, row); } /// /// Adds a FieldMarshal row /// /// New owner token /// Owner protected void AddFieldMarshal(MDToken parent, IHasFieldMarshal hfm) { if (hfm == null || hfm.MarshalType == null) return; var fieldMarshal = hfm.MarshalType; uint encodedParent; if (!CodedToken.HasFieldMarshal.Encode(parent, out encodedParent)) { Error("Can't encode HasFieldMarshal token {0:X8}", parent.Raw); encodedParent = 0; } var row = new RawFieldMarshalRow(encodedParent, blobHeap.Add(MarshalBlobWriter.Write(module, fieldMarshal, this))); fieldMarshalInfos.Add(hfm, row); } /// /// Adds a FieldRVA row /// /// The field protected void AddFieldRVA(FieldDef field) { Debug.Assert(!isStandaloneDebugMetadata); if (field.RVA != 0 && KeepFieldRVA) { uint rid = GetRid(field); var row = new RawFieldRVARow((uint)field.RVA, rid); fieldRVAInfos.Add(field, row); } else { if (field == null || field.InitialValue == null) return; var ivBytes = field.InitialValue; if (!VerifyFieldSize(field, ivBytes.Length)) Error("Field {0} ({1:X8}) initial value size != size of field type", field, field.MDToken.Raw); uint rid = GetRid(field); var iv = constants.Add(new ByteArrayChunk(ivBytes), ModuleWriterBase.DEFAULT_CONSTANTS_ALIGNMENT); fieldToInitialValue[field] = iv; var row = new RawFieldRVARow(0, rid); fieldRVAInfos.Add(field, row); } } static bool VerifyFieldSize(FieldDef field, int size) { if (field == null) return false; var sig = field.FieldSig; if (sig == null) return false; return field.GetFieldSize() == size; } /// /// Adds a ImplMap row /// /// New owner token /// Owner protected void AddImplMap(MDToken parent, IMemberForwarded mf) { if (mf == null || mf.ImplMap == null) return; var implMap = mf.ImplMap; uint encodedParent; if (!CodedToken.MemberForwarded.Encode(parent, out encodedParent)) { Error("Can't encode MemberForwarded token {0:X8}", parent.Raw); encodedParent = 0; } var row = new RawImplMapRow((ushort)implMap.Attributes, encodedParent, stringsHeap.Add(implMap.Name), AddModuleRef(implMap.Module)); implMapInfos.Add(mf, row); } /// /// Adds a Constant row /// /// New owner token /// Owner protected void AddConstant(MDToken parent, IHasConstant hc) { if (hc == null || hc.Constant == null) return; var constant = hc.Constant; uint encodedParent; if (!CodedToken.HasConstant.Encode(parent, out encodedParent)) { Error("Can't encode HasConstant token {0:X8}", parent.Raw); encodedParent = 0; } var row = new RawConstantRow((byte)constant.Type, 0, encodedParent, blobHeap.Add(GetConstantValueAsByteArray(constant.Type, constant.Value))); hasConstantInfos.Add(hc, row); } static readonly byte[] constantClassByteArray = new byte[4]; static readonly byte[] constantDefaultByteArray = new byte[8]; byte[] GetConstantValueAsByteArray(ElementType etype, object o) { if (o == null) { if (etype == ElementType.Class) return constantClassByteArray; Error("Constant is null"); return constantDefaultByteArray; } var typeCode = Type.GetTypeCode(o.GetType()); switch (typeCode) { case TypeCode.Boolean: VerifyConstantType(etype, ElementType.Boolean); return BitConverter.GetBytes((bool)o); case TypeCode.Char: VerifyConstantType(etype, ElementType.Char); return BitConverter.GetBytes((char)o); case TypeCode.SByte: VerifyConstantType(etype, ElementType.I1); return new byte[1] { (byte)(sbyte)o }; case TypeCode.Byte: VerifyConstantType(etype, ElementType.U1); return new byte[1] { (byte)o }; case TypeCode.Int16: VerifyConstantType(etype, ElementType.I2); return BitConverter.GetBytes((short)o); case TypeCode.UInt16: VerifyConstantType(etype, ElementType.U2); return BitConverter.GetBytes((ushort)o); case TypeCode.Int32: VerifyConstantType(etype, ElementType.I4); return BitConverter.GetBytes((int)o); case TypeCode.UInt32: VerifyConstantType(etype, ElementType.U4); return BitConverter.GetBytes((uint)o); case TypeCode.Int64: VerifyConstantType(etype, ElementType.I8); return BitConverter.GetBytes((long)o); case TypeCode.UInt64: VerifyConstantType(etype, ElementType.U8); return BitConverter.GetBytes((ulong)o); case TypeCode.Single: VerifyConstantType(etype, ElementType.R4); return BitConverter.GetBytes((float)o); case TypeCode.Double: VerifyConstantType(etype, ElementType.R8); return BitConverter.GetBytes((double)o); case TypeCode.String: VerifyConstantType(etype, ElementType.String); return Encoding.Unicode.GetBytes((string)o); default: Error("Invalid constant type: {0}", typeCode); return constantDefaultByteArray; } } void VerifyConstantType(ElementType realType, ElementType expectedType) { if (realType != expectedType) Error("Constant value's type is the wrong type: {0} != {1}", realType, expectedType); } /// /// Adds a DeclSecurity row /// /// New owner token /// All DeclSecurity rows protected void AddDeclSecurities(MDToken parent, IList declSecurities) { if (declSecurities == null) return; uint encodedParent; if (!CodedToken.HasDeclSecurity.Encode(parent, out encodedParent)) { Error("Can't encode HasDeclSecurity token {0:X8}", parent.Raw); encodedParent = 0; } var bwctx = AllocBinaryWriterContext(); foreach (var decl in declSecurities) { if (decl == null) continue; var row = new RawDeclSecurityRow((short)decl.Action, encodedParent, blobHeap.Add(DeclSecurityWriter.Write(module, decl.SecurityAttributes, this, bwctx))); declSecurityInfos.Add(decl, row); } Free(ref bwctx); } /// /// Adds MethodSemantics rows /// /// Event protected void AddMethodSemantics(EventDef evt) { if (evt == null) { Error("Event is null"); return; } uint rid = GetRid(evt); if (rid == 0) return; var token = new MDToken(Table.Event, rid); AddMethodSemantics(token, evt.AddMethod, MethodSemanticsAttributes.AddOn); AddMethodSemantics(token, evt.RemoveMethod, MethodSemanticsAttributes.RemoveOn); AddMethodSemantics(token, evt.InvokeMethod, MethodSemanticsAttributes.Fire); AddMethodSemantics(token, evt.OtherMethods, MethodSemanticsAttributes.Other); } /// /// Adds MethodSemantics rows /// /// Property protected void AddMethodSemantics(PropertyDef prop) { if (prop == null) { Error("Property is null"); return; } uint rid = GetRid(prop); if (rid == 0) return; var token = new MDToken(Table.Property, rid); AddMethodSemantics(token, prop.GetMethods, MethodSemanticsAttributes.Getter); AddMethodSemantics(token, prop.SetMethods, MethodSemanticsAttributes.Setter); AddMethodSemantics(token, prop.OtherMethods, MethodSemanticsAttributes.Other); } void AddMethodSemantics(MDToken owner, IList methods, MethodSemanticsAttributes attrs) { if (methods == null) return; foreach (var method in methods) AddMethodSemantics(owner, method, attrs); } void AddMethodSemantics(MDToken owner, MethodDef method, MethodSemanticsAttributes flags) { if (method == null) return; uint methodRid = GetRid(method); if (methodRid == 0) return; uint encodedOwner; if (!CodedToken.HasSemantic.Encode(owner, out encodedOwner)) { Error("Can't encode HasSemantic token {0:X8}", owner.Raw); encodedOwner = 0; } var row = new RawMethodSemanticsRow((ushort)flags, methodRid, encodedOwner); methodSemanticsInfos.Add(method, row); } void AddMethodImpls(MethodDef method, IList overrides) { if (overrides == null) return; if (method.DeclaringType == null) { Error("Method declaring type == null. Method {0} ({1:X8})", method, method.MDToken.Raw); return; } uint rid = GetRid(method.DeclaringType); foreach (var ovr in overrides) { var row = new RawMethodImplRow(rid, AddMethodDefOrRef(ovr.MethodBody), AddMethodDefOrRef(ovr.MethodDeclaration)); methodImplInfos.Add(method, row); } } /// /// Adds a ClassLayout row /// /// Type protected void AddClassLayout(TypeDef type) { if (type == null || type.ClassLayout == null) return; var rid = GetRid(type); var classLayout = type.ClassLayout; var row = new RawClassLayoutRow(classLayout.PackingSize, classLayout.ClassSize, rid); classLayoutInfos.Add(type, row); } void AddResources(IList resources) { if (resources == null) return; foreach (var resource in resources) AddResource(resource); } void AddResource(Resource resource) { var er = resource as EmbeddedResource; if (er != null) { AddEmbeddedResource(er); return; } var alr = resource as AssemblyLinkedResource; if (alr != null) { AddAssemblyLinkedResource(alr); return; } var lr = resource as LinkedResource; if (lr != null) { AddLinkedResource(lr); return; } if (resource == null) Error("Resource is null"); else Error("Invalid resource type: {0}", resource.GetType()); } uint AddEmbeddedResource(EmbeddedResource er) { Debug.Assert(!isStandaloneDebugMetadata); if (er == null) { Error("EmbeddedResource is null"); return 0; } uint rid; if (manifestResourceInfos.TryGetRid(er, out rid)) return rid; var row = new RawManifestResourceRow(netResources.NextOffset, (uint)er.Attributes, stringsHeap.Add(er.Name), 0); rid = tablesHeap.ManifestResourceTable.Add(row); manifestResourceInfos.Add(er, rid); embeddedResourceToByteArray[er] = netResources.Add(er.Data); //TODO: Add custom attributes //TODO: Add custom debug infos return rid; } uint AddAssemblyLinkedResource(AssemblyLinkedResource alr) { if (alr == null) { Error("AssemblyLinkedResource is null"); return 0; } uint rid; if (manifestResourceInfos.TryGetRid(alr, out rid)) return rid; var row = new RawManifestResourceRow(0, (uint)alr.Attributes, stringsHeap.Add(alr.Name), AddImplementation(alr.Assembly)); rid = tablesHeap.ManifestResourceTable.Add(row); manifestResourceInfos.Add(alr, rid); //TODO: Add custom attributes //TODO: Add custom debug infos return rid; } uint AddLinkedResource(LinkedResource lr) { if (lr == null) { Error("LinkedResource is null"); return 0; } uint rid; if (manifestResourceInfos.TryGetRid(lr, out rid)) return rid; var row = new RawManifestResourceRow(0, (uint)lr.Attributes, stringsHeap.Add(lr.Name), AddImplementation(lr.File)); rid = tablesHeap.ManifestResourceTable.Add(row); manifestResourceInfos.Add(lr, rid); //TODO: Add custom attributes //TODO: Add custom debug infos return rid; } /// /// Adds a File row /// /// File /// Its new rid protected uint AddFile(FileDef file) { if (file == null) { Error("FileDef is null"); return 0; } uint rid; if (fileDefInfos.TryGetRid(file, out rid)) return rid; var row = new RawFileRow((uint)file.Flags, stringsHeap.Add(file.Name), blobHeap.Add(file.HashValue)); //TODO: Re-calculate the hash value if possible rid = tablesHeap.FileTable.Add(row); fileDefInfos.Add(file, rid); AddCustomAttributes(Table.File, rid, file); AddCustomDebugInformationList(Table.File, rid, file); return rid; } /// /// Adds a ExportedType row /// /// Exported type /// Its new rid protected uint AddExportedType(ExportedType et) { if (et == null) { Error("ExportedType is null"); return 0; } uint rid; if (exportedTypeInfos.TryGetRid(et, out rid)) return rid; exportedTypeInfos.Add(et, 0); // Prevent inf recursion var row = new RawExportedTypeRow((uint)et.Attributes, et.TypeDefId, //TODO: Should be updated with the new rid stringsHeap.Add(et.TypeName), stringsHeap.Add(et.TypeNamespace), AddImplementation(et.Implementation)); rid = tablesHeap.ExportedTypeTable.Add(row); exportedTypeInfos.SetRid(et, rid); AddCustomAttributes(Table.ExportedType, rid, et); AddCustomDebugInformationList(Table.ExportedType, rid, et); return rid; } /// /// Gets a #Blob offset of a type signature /// /// Type sig /// Extra data to append the signature if /// is true. /// #Blob offset protected uint GetSignature(TypeSig ts, byte[] extraData) { byte[] blob; if (ts == null) { Error("TypeSig is null"); blob = null; } else { var bwctx = AllocBinaryWriterContext(); blob = SignatureWriter.Write(this, ts, bwctx); Free(ref bwctx); } AppendExtraData(ref blob, extraData); return blobHeap.Add(blob); } /// /// Gets a #Blob offset of a calling convention signature /// /// Signature /// #Blob offset protected uint GetSignature(CallingConventionSig sig) { if (sig == null) { Error("CallingConventionSig is null"); return 0; } var bwctx = AllocBinaryWriterContext(); var blob = SignatureWriter.Write(this, sig, bwctx); Free(ref bwctx); AppendExtraData(ref blob, sig.ExtraData); return blobHeap.Add(blob); } void AppendExtraData(ref byte[] blob, byte[] extraData) { if (PreserveExtraSignatureData && extraData != null && extraData.Length > 0) { int blen = blob == null ? 0 : blob.Length; Array.Resize(ref blob, blen + extraData.Length); Array.Copy(extraData, 0, blob, blen, extraData.Length); } } /// /// Adds a CustomAttribute row /// /// Owner table /// New owner rid /// Onwer protected void AddCustomAttributes(Table table, uint rid, IHasCustomAttribute hca) { AddCustomAttributes(table, rid, hca.CustomAttributes); } void AddCustomAttributes(Table table, uint rid, CustomAttributeCollection caList) { var token = new MDToken(table, rid); foreach (var ca in caList) AddCustomAttribute(token, ca); } void AddCustomAttribute(MDToken token, CustomAttribute ca) { if (ca == null) { Error("Custom attribute is null"); return; } uint encodedToken; if (!CodedToken.HasCustomAttribute.Encode(token, out encodedToken)) { Error("Can't encode HasCustomAttribute token {0:X8}", token.Raw); encodedToken = 0; } var bwctx = AllocBinaryWriterContext(); var caBlob = CustomAttributeWriter.Write(this, ca, bwctx); Free(ref bwctx); var row = new RawCustomAttributeRow(encodedToken, AddCustomAttributeType(ca.Constructor), blobHeap.Add(caBlob)); customAttributeInfos.Add(ca, row); } void AddCustomDebugInformationList(MethodDef method, uint rid, uint localVarSigToken) { if (debugMetaData == null) return; var serializerMethodContext = AllocSerializerMethodContext(); serializerMethodContext.SetBody(method); if (method.CustomDebugInfos.Count != 0) AddCustomDebugInformationCore(serializerMethodContext, Table.Method, rid, method.CustomDebugInfos); AddMethodDebugInformation(method, rid, localVarSigToken); Free(ref serializerMethodContext); } void AddMethodDebugInformation(MethodDef method, uint rid, uint localVarSigToken) { Debug.Assert(debugMetaData != null); var body = method.Body; if (body == null) return; bool hasNoSeqPoints; PdbDocument singleDoc, firstDoc; GetSingleDocument(body, out singleDoc, out firstDoc, out hasNoSeqPoints); if (hasNoSeqPoints) return; var bwctx = AllocBinaryWriterContext(); var outStream = bwctx.OutStream; var writer = bwctx.Writer; outStream.SetLength(0); outStream.Position = 0; writer.WriteCompressedUInt32(localVarSigToken); if (singleDoc == null) writer.WriteCompressedUInt32(VerifyGetRid(firstDoc)); var instrs = body.Instructions; var currentDoc = firstDoc; uint ilOffset = uint.MaxValue; int line = -1, column = 0; uint instrOffset = 0; Instruction instr = null; for (int i = 0; i < instrs.Count; i++, instrOffset += (uint)instr.GetSize()) { instr = instrs[i]; var seqPoint = instr.SequencePoint; if (seqPoint == null) continue; if (seqPoint.Document == null) { Error("PDB document is null"); return; } if (currentDoc != seqPoint.Document) { // document-record currentDoc = seqPoint.Document; writer.WriteCompressedUInt32(0); writer.WriteCompressedUInt32(VerifyGetRid(currentDoc)); } // SequencePointRecord if (ilOffset == uint.MaxValue) writer.WriteCompressedUInt32(instrOffset); else writer.WriteCompressedUInt32(instrOffset - ilOffset); ilOffset = instrOffset; if (seqPoint.StartLine == SequencePointConstants.HIDDEN_LINE && seqPoint.EndLine == SequencePointConstants.HIDDEN_LINE) { // hidden-sequence-point-record writer.WriteCompressedUInt32(0); writer.WriteCompressedUInt32(0); } else { // sequence-point-record uint dlines = (uint)(seqPoint.EndLine - seqPoint.StartLine); int dcolumns = seqPoint.EndColumn - seqPoint.StartColumn; writer.WriteCompressedUInt32(dlines); if (dlines == 0) writer.WriteCompressedUInt32((uint)dcolumns); else writer.WriteCompressedInt32(dcolumns); if (line < 0) { writer.WriteCompressedUInt32((uint)seqPoint.StartLine); writer.WriteCompressedUInt32((uint)seqPoint.StartColumn); } else { writer.WriteCompressedInt32(seqPoint.StartLine - line); writer.WriteCompressedInt32(seqPoint.StartColumn - column); } line = seqPoint.StartLine; column = seqPoint.StartColumn; } } var seqPointsBlob = outStream.ToArray(); var row = debugMetaData.tablesHeap.MethodDebugInformationTable[rid]; row.Document = singleDoc == null ? 0 : AddPdbDocument(singleDoc); row.SequencePoints = debugMetaData.blobHeap.Add(seqPointsBlob); debugMetaData.methodDebugInformationInfosUsed = true; Free(ref bwctx); } uint VerifyGetRid(PdbDocument doc) { Debug.Assert(debugMetaData != null); uint rid; if (!debugMetaData.pdbDocumentInfos.TryGetRid(doc, out rid)) { Error("PDB document has been removed"); return 0; } return rid; } static void GetSingleDocument(CilBody body, out PdbDocument singleDoc, out PdbDocument firstDoc, out bool hasNoSeqPoints) { var instrs = body.Instructions; int docCount = 0; singleDoc = null; firstDoc = null; for (int i = 0; i < instrs.Count; i++) { var seqPt = instrs[i].SequencePoint; if (seqPt == null) continue; var doc = seqPt.Document; if (doc == null) continue; if (firstDoc == null) firstDoc = doc; if (singleDoc != doc) { singleDoc = doc; docCount++; if (docCount > 1) break; } } hasNoSeqPoints = docCount == 0; if (docCount != 1) singleDoc = null; } /// /// Adds a CustomDebugInformation row /// /// Owner table /// New owner rid /// Onwer protected void AddCustomDebugInformationList(Table table, uint rid, IHasCustomDebugInformation hcdi) { Debug.Assert(table != Table.Method); if (debugMetaData == null) return; if (hcdi.CustomDebugInfos.Count == 0) return; var serializerMethodContext = AllocSerializerMethodContext(); serializerMethodContext.SetBody(null); AddCustomDebugInformationCore(serializerMethodContext, table, rid, hcdi.CustomDebugInfos); Free(ref serializerMethodContext); } void AddCustomDebugInformationList(Table table, uint rid, IList cdis) { Debug.Assert(table != Table.Method); if (debugMetaData == null) return; if (cdis.Count == 0) return; var serializerMethodContext = AllocSerializerMethodContext(); serializerMethodContext.SetBody(null); AddCustomDebugInformationCore(serializerMethodContext, table, rid, cdis); Free(ref serializerMethodContext); } void AddCustomDebugInformationCore(SerializerMethodContext serializerMethodContext, Table table, uint rid, IList cdis) { Debug.Assert(debugMetaData != null); Debug.Assert(cdis.Count != 0); var token = new MDToken(table, rid); uint encodedToken; if (!CodedToken.HasCustomDebugInformation.Encode(token, out encodedToken)) { Error("Couldn't encode HasCustomDebugInformation token {0:X8}", token.Raw); return; } for (int i = 0; i < cdis.Count; i++) { var cdi = cdis[i]; if (cdi == null) { Error("Custom debug info is null"); continue; } AddCustomDebugInformation(serializerMethodContext, token.Raw, encodedToken, cdi); } } void AddCustomDebugInformation(SerializerMethodContext serializerMethodContext, uint token, uint encodedToken, PdbCustomDebugInfo cdi) { Debug.Assert(debugMetaData != null); switch (cdi.Kind) { case PdbCustomDebugInfoKind.UsingGroups: case PdbCustomDebugInfoKind.ForwardMethodInfo: case PdbCustomDebugInfoKind.ForwardModuleInfo: case PdbCustomDebugInfoKind.StateMachineTypeName: case PdbCustomDebugInfoKind.DynamicLocals: case PdbCustomDebugInfoKind.TupleElementNames: // These are Windows PDB CDIs Error("Unsupported custom debug info {0}", cdi.Kind); break; case PdbCustomDebugInfoKind.StateMachineHoistedLocalScopes: case PdbCustomDebugInfoKind.EditAndContinueLocalSlotMap: case PdbCustomDebugInfoKind.EditAndContinueLambdaMap: case PdbCustomDebugInfoKind.Unknown: case PdbCustomDebugInfoKind.TupleElementNames_PortablePdb: case PdbCustomDebugInfoKind.DefaultNamespace: case PdbCustomDebugInfoKind.DynamicLocalVariables: case PdbCustomDebugInfoKind.EmbeddedSource: case PdbCustomDebugInfoKind.SourceLink: AddCustomDebugInformationCore(serializerMethodContext, encodedToken, cdi, cdi.Guid); break; case PdbCustomDebugInfoKind.AsyncMethod: // This is a portable PDB pseudo CDI AddCustomDebugInformationCore(serializerMethodContext, encodedToken, cdi, CustomDebugInfoGuids.AsyncMethodSteppingInformationBlob); AddStateMachineMethod(cdi, token, ((PdbAsyncMethodCustomDebugInfo)cdi).KickoffMethod); break; case PdbCustomDebugInfoKind.IteratorMethod: // This is a portable PDB pseudo CDI AddStateMachineMethod(cdi, token, ((PdbIteratorMethodCustomDebugInfo)cdi).KickoffMethod); break; default: Error("Unknown custom debug info {0}", cdi.Kind.ToString()); break; } } void AddStateMachineMethod(PdbCustomDebugInfo cdi, uint moveNextMethodToken, MethodDef kickoffMethod) { Debug.Assert(new MDToken(moveNextMethodToken).Table == Table.Method); Debug.Assert(debugMetaData != null); if (kickoffMethod == null) { Error("KickoffMethod is null"); return; } var row = new RawStateMachineMethodRow(new MDToken(moveNextMethodToken).Rid, GetRid(kickoffMethod)); debugMetaData.stateMachineMethodInfos.Add(cdi, row); } void AddCustomDebugInformationCore(SerializerMethodContext serializerMethodContext, uint encodedToken, PdbCustomDebugInfo cdi, Guid cdiGuid) { Debug.Assert(debugMetaData != null); var bwctx = AllocBinaryWriterContext(); var cdiBlob = PortablePdbCustomDebugInfoWriter.Write(this, serializerMethodContext, this, cdi, bwctx); Debug.Assert(cdiGuid != Guid.Empty); Free(ref bwctx); var row = new RawCustomDebugInformationRow(encodedToken, debugMetaData.guidHeap.Add(cdiGuid), debugMetaData.blobHeap.Add(cdiBlob)); debugMetaData.customDebugInfos.Add(cdi, row); } void InitializeMethodDebugInformation() { if (debugMetaData == null) return; int numMethods = NumberOfMethods; for (int i = 0; i < numMethods; i++) debugMetaData.tablesHeap.MethodDebugInformationTable.Create(new RawMethodDebugInformationRow()); } void AddPdbDocuments() { if (debugMetaData == null) return; foreach (var doc in module.PdbState.Documents) AddPdbDocument(doc); } uint AddPdbDocument(PdbDocument doc) { Debug.Assert(debugMetaData != null); if (doc == null) { Error("PdbDocument is null"); return 0; } uint rid; if (debugMetaData.pdbDocumentInfos.TryGetRid(doc, out rid)) return rid; var row = new RawDocumentRow(GetDocumentNameBlobOffset(doc.Url), debugMetaData.guidHeap.Add(doc.CheckSumAlgorithmId), debugMetaData.blobHeap.Add(doc.CheckSum), debugMetaData.guidHeap.Add(doc.Language)); rid = debugMetaData.tablesHeap.DocumentTable.Add(row); debugMetaData.pdbDocumentInfos.Add(doc, rid); AddCustomDebugInformationList(Table.Document, rid, doc.CustomDebugInfos); return rid; } uint GetDocumentNameBlobOffset(string name) { Debug.Assert(debugMetaData != null); if (name == null) { Error("Document name is null"); name = string.Empty; } var bwctx = AllocBinaryWriterContext(); var outStream = bwctx.OutStream; var writer = bwctx.Writer; outStream.SetLength(0); outStream.Position = 0; var parts = name.Split(directorySeparatorCharArray); if (parts.Length == 1) writer.Write((byte)0); else writer.Write(directorySeparatorCharUtf8); for (int i = 0; i < parts.Length; i++) { var part = parts[i]; uint partOffset = debugMetaData.blobHeap.Add(Encoding.UTF8.GetBytes(part)); writer.WriteCompressedUInt32(partOffset); } var res = debugMetaData.blobHeap.Add(outStream.ToArray()); Free(ref bwctx); return res; } static readonly byte[] directorySeparatorCharUtf8 = Encoding.UTF8.GetBytes(Path.DirectorySeparatorChar.ToString()); static readonly char[] directorySeparatorCharArray = new char[] { Path.DirectorySeparatorChar }; uint AddImportScope(PdbImportScope scope) { Debug.Assert(debugMetaData != null); if (scope == null) return 0; uint rid; if (debugMetaData.importScopeInfos.TryGetRid(scope, out rid)) { if (rid == 0) Error("PdbImportScope has an infinite Parent loop"); return rid; } debugMetaData.importScopeInfos.Add(scope, 0); // Prevent inf recursion var bwctx = AllocBinaryWriterContext(); var outStream = bwctx.OutStream; var writer = bwctx.Writer; outStream.SetLength(0); outStream.Position = 0; ImportScopeBlobWriter.Write(this, this, writer, debugMetaData.blobHeap, scope.Imports); var importsData = outStream.ToArray(); Free(ref bwctx); var row = new RawImportScopeRow(AddImportScope(scope.Parent), debugMetaData.blobHeap.Add(importsData)); rid = debugMetaData.tablesHeap.ImportScopeTable.Add(row); debugMetaData.importScopeInfos.SetRid(scope, rid); AddCustomDebugInformationList(Table.ImportScope, rid, scope.CustomDebugInfos); return rid; } void AddLocalVariable(PdbLocal local) { Debug.Assert(debugMetaData != null); if (local == null) { Error("PDB local is null"); return; } var row = new RawLocalVariableRow((ushort)local.Attributes, (ushort)local.Index, debugMetaData.stringsHeap.Add(local.Name)); uint rid = debugMetaData.tablesHeap.LocalVariableTable.Create(row); debugMetaData.localVariableInfos.Add(local, rid); AddCustomDebugInformationList(Table.LocalVariable, rid, local.CustomDebugInfos); } void AddLocalConstant(PdbConstant constant) { Debug.Assert(debugMetaData != null); if (constant == null) { Error("PDB constant is null"); return; } var bwctx = AllocBinaryWriterContext(); var outStream = bwctx.OutStream; var writer = bwctx.Writer; outStream.SetLength(0); outStream.Position = 0; LocalConstantSigBlobWriter.Write(this, this, writer, constant.Type, constant.Value); var signature = outStream.ToArray(); Free(ref bwctx); var row = new RawLocalConstantRow(debugMetaData.stringsHeap.Add(constant.Name), debugMetaData.blobHeap.Add(signature)); uint rid = debugMetaData.tablesHeap.LocalConstantTable.Create(row); debugMetaData.localConstantInfos.Add(constant, rid); AddCustomDebugInformationList(Table.LocalConstant, rid, constant.CustomDebugInfos); } /// /// Writes the portable PDB to . /// /// Output stream /// Entry point token /// PDB ID, exactly 20 bytes internal void WritePortablePdb(Stream output, uint entryPointToken, byte[] pdbId) { if (debugMetaData == null) throw new InvalidOperationException(); if (pdbId.Length != 20) throw new InvalidOperationException(); var pdbHeap = debugMetaData.PdbHeap; pdbHeap.EntryPoint = entryPointToken; for (int i = 0; i < pdbId.Length; i++) pdbHeap.PdbId[i] = pdbId[i]; ulong systemTablesMask; tablesHeap.GetSystemTableRows(out systemTablesMask, pdbHeap.TypeSystemTableRows); debugMetaData.tablesHeap.SetSystemTableRows(pdbHeap.TypeSystemTableRows); if (!debugMetaData.methodDebugInformationInfosUsed) debugMetaData.tablesHeap.MethodDebugInformationTable.Reset(); pdbHeap.ReferencedTypeSystemTables = systemTablesMask; var writer = new BinaryWriter(output); debugMetaData.SetOffset(0, 0); debugMetaData.GetFileLength(); debugMetaData.VerifyWriteTo(writer); } /// uint ISignatureWriterHelper.ToEncodedToken(ITypeDefOrRef typeDefOrRef) { return AddTypeDefOrRef(typeDefOrRef); } /// void IWriterError.Error(string message) { Error(message); } /// bool IFullNameCreatorHelper.MustUseAssemblyName(IType type) { return FullNameCreator.MustUseAssemblyName(module, type); } /// /// Called before any other methods /// protected virtual void Initialize() { } /// /// Gets all s that should be saved in the meta data /// protected abstract List GetAllTypeDefs(); /// /// Initializes TypeDef rids and creates raw rows, but does not initialize /// any columns. /// protected abstract void AllocateTypeDefRids(); /// /// Allocates Field, Method, Property, Event, Param: /// rid and raw row, but doesn't initialize the raw row. /// Initializes TypeDef columns: FieldList, MethodList. /// Initializes Method column: ParamList. /// Initializes and . /// protected abstract void AllocateMemberDefRids(); /// /// Adds a . Its custom attributes are also added. /// /// Type reference /// Its new rid protected abstract uint AddTypeRef(TypeRef tr); /// /// Adds a . Its custom attributes are also added. /// /// Type spec /// Its new rid protected abstract uint AddTypeSpec(TypeSpec ts); /// /// Adds a . Its custom attributes are also added. /// /// Member ref /// Its new rid protected abstract uint AddMemberRef(MemberRef mr); /// /// Adds a . Its custom attributes are also added. /// /// Stand alone sig /// Its new rid protected abstract uint AddStandAloneSig(StandAloneSig sas); /// /// Adds a . Its custom attributes are also added. /// /// Method spec /// Its new rid protected abstract uint AddMethodSpec(MethodSpec ms); /// /// Called before sorting the CustomAttribute table. This is the last time anything /// can be inserted into this table. /// protected virtual void BeforeSortingCustomAttributes() { } /// /// Called after everything has been initialized. The sub class can initialize more /// rows if necessary or do nothing. After this method has been called, nothing else /// can be added. /// protected virtual void EverythingInitialized() { } const uint HEAP_ALIGNMENT = 4; /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; stringsHeap.AddOptimizedStrings(); stringsHeap.SetReadOnly(); blobHeap.SetReadOnly(); guidHeap.SetReadOnly(); tablesHeap.SetReadOnly(); pdbHeap.SetReadOnly(); tablesHeap.BigStrings = stringsHeap.IsBig; tablesHeap.BigBlob = blobHeap.IsBig; tablesHeap.BigGuid = guidHeap.IsBig; metaDataHeader.Heaps = GetHeaps(); metaDataHeader.SetOffset(offset, rva); uint len = metaDataHeader.GetFileLength(); offset += len; rva += len; foreach (var heap in metaDataHeader.Heaps) { offset = offset.AlignUp(HEAP_ALIGNMENT); rva = rva.AlignUp(HEAP_ALIGNMENT); heap.SetOffset(offset, rva); len = heap.GetFileLength(); offset += len; rva += len; } length = rva - this.rva; if (!isStandaloneDebugMetadata) { UpdateMethodRvas(); UpdateFieldRvas(); } } IList GetHeaps() { var heaps = new List(); if (isStandaloneDebugMetadata) { heaps.Add(pdbHeap); heaps.Add(tablesHeap); if (!stringsHeap.IsEmpty) heaps.Add(stringsHeap); if (!usHeap.IsEmpty) heaps.Add(usHeap); if (!guidHeap.IsEmpty) heaps.Add(guidHeap); if (!blobHeap.IsEmpty) heaps.Add(blobHeap); } else { if (options.OtherHeaps != null) heaps.AddRange(options.OtherHeaps); // The #! heap must be added before the other heaps or the CLR can // sometimes flag an error. Eg., it can check whether a pointer is valid. // It does this by comparing the pointer to the last valid address for // the particular heap. If this pointer really is in the #! heap and the // #! heap is at an address > than the other heap, then the CLR will think // it's an invalid pointer. if (hotHeap != null) // Don't check whether it's empty heaps.Add(hotHeap); heaps.Add(tablesHeap); if (!stringsHeap.IsEmpty || AlwaysCreateStringsHeap) heaps.Add(stringsHeap); if (!usHeap.IsEmpty || AlwaysCreateUSHeap) heaps.Add(usHeap); if (!guidHeap.IsEmpty || AlwaysCreateGuidHeap) heaps.Add(guidHeap); if (!blobHeap.IsEmpty || AlwaysCreateBlobHeap) heaps.Add(blobHeap); if (options.OtherHeapsEnd != null) heaps.AddRange(options.OtherHeapsEnd); } return heaps; } /// public uint GetFileLength() { return length; } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { var rva2 = rva; metaDataHeader.VerifyWriteTo(writer); rva2 += metaDataHeader.GetFileLength(); foreach (var heap in metaDataHeader.Heaps) { writer.WriteZeros((int)(rva2.AlignUp(HEAP_ALIGNMENT) - rva2)); rva2 = rva2.AlignUp(HEAP_ALIGNMENT); heap.VerifyWriteTo(writer); rva2 += heap.GetFileLength(); } } /// /// Sorts the s /// /// All s /// A sorted list protected static List Sort(IEnumerable pds) { var sorted = new List(pds); sorted.Sort((a, b) => { if (a == null) return -1; if (b == null) return 1; return a.Sequence.CompareTo(b.Sequence); }); return sorted; } BinaryWriterContext AllocBinaryWriterContext() { if (binaryWriterContexts.Count == 0) return new BinaryWriterContext(); var res = binaryWriterContexts[binaryWriterContexts.Count - 1]; binaryWriterContexts.RemoveAt(binaryWriterContexts.Count - 1); return res; } void Free(ref BinaryWriterContext ctx) { binaryWriterContexts.Add(ctx); ctx = null; } SerializerMethodContext AllocSerializerMethodContext() { if (serializerMethodContexts.Count == 0) return new SerializerMethodContext(this); var res = serializerMethodContexts[serializerMethodContexts.Count - 1]; serializerMethodContexts.RemoveAt(serializerMethodContexts.Count - 1); return res; } void Free(ref SerializerMethodContext ctx) { serializerMethodContexts.Add(ctx); ctx = null; } } } dnlib-2.1_VS2010/src/DotNet/Writer/MetaDataHeader.cs000066400000000000000000000106161325033663500217510ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.IO; using System.Text; using dnlib.IO; using dnlib.PE; using dnlib.DotNet.MD; namespace dnlib.DotNet.Writer { /// /// options /// public sealed class MetaDataHeaderOptions { /// /// Default version string /// public const string DEFAULT_VERSION_STRING = MDHeaderRuntimeVersion.MS_CLR_20; /// /// Default header signature /// public const uint DEFAULT_SIGNATURE = 0x424A5342; /// /// MD header signature. Default value is /// public uint? Signature; /// /// Major version. Default is 1. MS' CLR supports v0.x (x >= 19) and v1.1, nothing else. /// public ushort? MajorVersion; /// /// Minor version. Default is 1. /// public ushort? MinorVersion; /// /// Reserved and should be 0. /// public uint? Reserved1; /// /// Version string. Default is . It's stored as a /// zero-terminated UTF-8 string. Length should be <= 255 bytes. /// public string VersionString; /// /// Storage flags should be 0 /// public StorageFlags? StorageFlags; /// /// Reserved and should be 0 /// public byte? Reserved2; /// /// Creates portable PDB v1.0 options /// /// public static MetaDataHeaderOptions CreatePortablePdbV1_0() { return new MetaDataHeaderOptions() { Signature = DEFAULT_SIGNATURE, MajorVersion = 1, MinorVersion = 1, Reserved1 = 0, VersionString = MDHeaderRuntimeVersion.PORTABLE_PDB_V1_0, StorageFlags = 0, Reserved2 = 0, }; } } /// /// Meta data header. IMAGE_COR20_HEADER.MetaData points to this header. /// public sealed class MetaDataHeader : IChunk { IList heaps; readonly MetaDataHeaderOptions options; uint length; FileOffset offset; RVA rva; /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Gets/sets the heaps /// public IList Heaps { get { return heaps; } set { heaps = value; } } /// /// Default constructor /// public MetaDataHeader() : this(null) { } /// /// Constructor /// /// Options public MetaDataHeader(MetaDataHeaderOptions options) { this.options = options ?? new MetaDataHeaderOptions(); } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; length = 16; length += (uint)GetVersionString().Length; length = Utils.AlignUp(length, 4); length += 4; foreach (var heap in heaps) { length += 8; length += (uint)GetAsciizName(heap.Name).Length; length = Utils.AlignUp(length, 4); } } /// public uint GetFileLength() { return length; } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { writer.Write(options.Signature ?? MetaDataHeaderOptions.DEFAULT_SIGNATURE); writer.Write(options.MajorVersion ?? 1); writer.Write(options.MinorVersion ?? 1); writer.Write(options.Reserved1 ?? 0); var s = GetVersionString(); writer.Write(Utils.AlignUp(s.Length, 4)); writer.Write(s); writer.WriteZeros(Utils.AlignUp(s.Length, 4) - s.Length); writer.Write((byte)(options.StorageFlags ?? 0)); writer.Write(options.Reserved2 ?? 0); writer.Write((ushort)heaps.Count); foreach (var heap in heaps) { writer.Write((uint)(heap.FileOffset - offset)); writer.Write(heap.GetFileLength()); writer.Write(s = GetAsciizName(heap.Name)); if (s.Length > 32) throw new ModuleWriterException(string.Format("Heap name '{0}' is > 32 bytes", heap.Name)); writer.WriteZeros(Utils.AlignUp(s.Length, 4) - s.Length); } } byte[] GetVersionString() { return Encoding.UTF8.GetBytes((options.VersionString ?? MetaDataHeaderOptions.DEFAULT_VERSION_STRING) + "\0"); } byte[] GetAsciizName(string s) { return Encoding.ASCII.GetBytes(s + "\0"); } } } dnlib-2.1_VS2010/src/DotNet/Writer/MethodBody.cs000066400000000000000000000073611325033663500212210ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Method body chunk /// public sealed class MethodBody : IChunk { const uint EXTRA_SECTIONS_ALIGNMENT = 4; readonly bool isTiny; readonly byte[] code; readonly byte[] extraSections; uint length; FileOffset offset; RVA rva; uint localVarSigTok; /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Gets the code /// public byte[] Code { get { return code; } } /// /// Gets the extra sections (exception handlers) or null /// public byte[] ExtraSections { get { return extraSections; } } /// /// Gets the token of the locals /// public uint LocalVarSigTok { get { return localVarSigTok; } } /// /// true if it's a fat body /// public bool IsFat { get { return !isTiny; } } /// /// true if it's a tiny body /// public bool IsTiny { get { return isTiny; } } /// /// true if there's an extra section /// public bool HasExtraSections { get { return extraSections != null && extraSections.Length > 0; } } /// /// Constructor /// /// Code public MethodBody(byte[] code) : this(code, null, 0) { } /// /// Constructor /// /// Code /// Extra sections or null public MethodBody(byte[] code, byte[] extraSections) : this(code, extraSections, 0) { } /// /// Constructor /// /// Code /// Extra sections or null /// Token of locals public MethodBody(byte[] code, byte[] extraSections, uint localVarSigTok) { this.isTiny = (code[0] & 3) == 2; this.code = code; this.extraSections = extraSections; this.localVarSigTok = localVarSigTok; } /// /// Gets the approximate size of the method body (code + exception handlers) /// public int GetSizeOfMethodBody() { int len = code.Length; if (extraSections != null) { len = Utils.AlignUp(len, EXTRA_SECTIONS_ALIGNMENT); len += extraSections.Length; len = Utils.AlignUp(len, EXTRA_SECTIONS_ALIGNMENT); } return len; } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; if (HasExtraSections) { RVA rva2 = rva + (uint)code.Length; rva2 = rva2.AlignUp(EXTRA_SECTIONS_ALIGNMENT); rva2 += (uint)extraSections.Length; length = (uint)rva2 - (uint)rva; } else length = (uint)code.Length; } /// public uint GetFileLength() { return length; } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { writer.Write(code); if (HasExtraSections) { RVA rva2 = rva + (uint)code.Length; writer.WriteZeros((int)rva2.AlignUp(EXTRA_SECTIONS_ALIGNMENT) - (int)rva2); writer.Write(extraSections); } } /// public override int GetHashCode() { return Utils.GetHashCode(code) + Utils.GetHashCode(extraSections); } /// public override bool Equals(object obj) { var other = obj as MethodBody; if (other == null) return false; return Utils.Equals(code, other.code) && Utils.Equals(extraSections, other.extraSections); } } } dnlib-2.1_VS2010/src/DotNet/Writer/MethodBodyChunks.cs000066400000000000000000000067351325033663500224010ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Stores all method body chunks /// public sealed class MethodBodyChunks : IChunk { const uint FAT_BODY_ALIGNMENT = 4; Dictionary tinyMethodsDict; Dictionary fatMethodsDict; readonly List tinyMethods; readonly List fatMethods; readonly bool shareBodies; FileOffset offset; RVA rva; uint length; bool setOffsetCalled; readonly bool alignFatBodies; uint savedBytes; /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Gets the number of bytes saved by re-using method bodies /// public uint SavedBytes { get { return savedBytes; } } /// /// Constructor /// /// true if bodies can be shared public MethodBodyChunks(bool shareBodies) { this.shareBodies = shareBodies; this.alignFatBodies = true; if (shareBodies) { tinyMethodsDict = new Dictionary(); fatMethodsDict = new Dictionary(); } tinyMethods = new List(); fatMethods = new List(); } /// /// Adds a and returns the one that has been cached /// /// The method body /// The cached method body public MethodBody Add(MethodBody methodBody) { if (setOffsetCalled) throw new InvalidOperationException("SetOffset() has already been called"); if (shareBodies) { var dict = methodBody.IsFat ? fatMethodsDict : tinyMethodsDict; MethodBody cached; if (dict.TryGetValue(methodBody, out cached)) { savedBytes += (uint)methodBody.GetSizeOfMethodBody(); return cached; } dict[methodBody] = methodBody; } var list = methodBody.IsFat ? fatMethods : tinyMethods; list.Add(methodBody); return methodBody; } /// public void SetOffset(FileOffset offset, RVA rva) { setOffsetCalled = true; this.offset = offset; this.rva = rva; tinyMethodsDict = null; fatMethodsDict = null; var rva2 = rva; foreach (var mb in tinyMethods) { mb.SetOffset(offset, rva2); uint len = mb.GetFileLength(); rva2 += len; offset += len; } foreach (var mb in fatMethods) { if (alignFatBodies) { uint padding = (uint)rva2.AlignUp(FAT_BODY_ALIGNMENT) - (uint)rva2; rva2 += padding; offset += padding; } mb.SetOffset(offset, rva2); uint len = mb.GetFileLength(); rva2 += len; offset += len; } length = (uint)rva2 - (uint)rva; } /// public uint GetFileLength() { return length; } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { var rva2 = rva; foreach (var mb in tinyMethods) { mb.VerifyWriteTo(writer); rva2 += mb.GetFileLength(); } foreach (var mb in fatMethods) { if (alignFatBodies) { int padding = (int)rva2.AlignUp(FAT_BODY_ALIGNMENT) - (int)rva2; writer.WriteZeros(padding); rva2 += (uint)padding; } mb.VerifyWriteTo(writer); rva2 += mb.GetFileLength(); } } } } dnlib-2.1_VS2010/src/DotNet/Writer/MethodBodyWriter.cs000066400000000000000000000236221325033663500224140ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using System.Text; using dnlib.DotNet.Emit; namespace dnlib.DotNet.Writer { /// /// Returns tokens of token types, strings and signatures /// public interface ITokenCreator : IWriterError { /// /// Gets the token of /// /// A token type or a string or a signature /// The token MDToken GetToken(object o); /// /// Gets a StandAloneSig token /// /// All locals /// The original token or 0 if none /// A StandAloneSig token or 0 if is /// empty. MDToken GetToken(IList locals, uint origToken); } /// /// Writes CIL method bodies /// public sealed class MethodBodyWriter : MethodBodyWriterBase { readonly ITokenCreator helper; CilBody cilBody; bool keepMaxStack; uint codeSize; uint maxStack; byte[] code; byte[] extraSections; uint localVarSigTok; /// /// Gets the code as a byte array. This is valid only after calling . /// The size of this array is not necessarily a multiple of 4, even if there are exception /// handlers present. See also /// public byte[] Code { get { return code; } } /// /// Gets the extra sections (exception handlers) as a byte array or null if there /// are no exception handlers. This is valid only after calling /// public byte[] ExtraSections { get { return extraSections; } } /// /// Gets the token of the locals /// public uint LocalVarSigTok { get { return localVarSigTok; } } /// /// Constructor /// /// Helps this instance /// The CIL method body public MethodBodyWriter(ITokenCreator helper, CilBody cilBody) : this(helper, cilBody, false) { } /// /// Constructor /// /// Helps this instance /// The CIL method body /// Keep the original max stack value that has been initialized /// in public MethodBodyWriter(ITokenCreator helper, CilBody cilBody, bool keepMaxStack) : base(cilBody.Instructions, cilBody.ExceptionHandlers) { this.helper = helper; this.cilBody = cilBody; this.keepMaxStack = keepMaxStack; } internal MethodBodyWriter(ITokenCreator helper) { this.helper = helper; } internal void Reset(CilBody cilBody, bool keepMaxStack) { Reset(cilBody.Instructions, cilBody.ExceptionHandlers); this.cilBody = cilBody; this.keepMaxStack = keepMaxStack; codeSize = 0; maxStack = 0; code = null; extraSections = null; localVarSigTok = 0; } /// /// Writes the method body /// public void Write() { codeSize = InitializeInstructionOffsets(); maxStack = keepMaxStack ? cilBody.MaxStack : GetMaxStack(); if (NeedFatHeader()) WriteFatHeader(); else WriteTinyHeader(); if (exceptionHandlers.Count > 0) WriteExceptionHandlers(); } /// /// Gets the code and (possible) exception handlers in one array. The exception handlers /// are 4-byte aligned. /// /// The code and any exception handlers public byte[] GetFullMethodBody() { int padding = Utils.AlignUp(code.Length, 4) - code.Length; var bytes = new byte[code.Length + (extraSections == null ? 0 : padding + extraSections.Length)]; Array.Copy(code, 0, bytes, 0, code.Length); if (extraSections != null) Array.Copy(extraSections, 0, bytes, code.Length + padding, extraSections.Length); return bytes; } bool NeedFatHeader() { //TODO: If locals has cust attrs, we also need a fat header return codeSize > 0x3F || exceptionHandlers.Count > 0 || cilBody.HasVariables || maxStack > 8; } void WriteFatHeader() { if (maxStack > ushort.MaxValue) { Error("MaxStack is too big"); maxStack = ushort.MaxValue; } ushort flags = 0x3003; if (exceptionHandlers.Count > 0) flags |= 8; if (cilBody.InitLocals) flags |= 0x10; code = new byte[12 + codeSize]; var writer = new BinaryWriter(new MemoryStream(code), Encoding.UTF8); writer.Write(flags); writer.Write((ushort)maxStack); writer.Write(codeSize); writer.Write(localVarSigTok = helper.GetToken(GetLocals(), cilBody.LocalVarSigTok).Raw); if (WriteInstructions(writer) != codeSize) Error("Didn't write all code bytes"); } IList GetLocals() { var localsSig = new TypeSig[cilBody.Variables.Count]; for (int i = 0; i < cilBody.Variables.Count; i++) localsSig[i] = cilBody.Variables[i].Type; return localsSig; } void WriteTinyHeader() { localVarSigTok = 0; code = new byte[1 + codeSize]; var writer = new BinaryWriter(new MemoryStream(code), Encoding.UTF8); writer.Write((byte)((codeSize << 2) | 2)); if (WriteInstructions(writer) != codeSize) Error("Didn't write all code bytes"); } void WriteExceptionHandlers() { var outStream = new MemoryStream(); var writer = new BinaryWriter(outStream, Encoding.UTF8); if (NeedFatExceptionClauses()) WriteFatExceptionClauses(writer); else WriteSmallExceptionClauses(writer); extraSections = outStream.ToArray(); } bool NeedFatExceptionClauses() { // Size must fit in a byte, and since one small exception record is 12 bytes // and header is 4 bytes: x*12+4 <= 255 ==> x <= 20 if (exceptionHandlers.Count > 20) return true; foreach (var eh in exceptionHandlers) { if (!FitsInSmallExceptionClause(eh.TryStart, eh.TryEnd)) return true; if (!FitsInSmallExceptionClause(eh.HandlerStart, eh.HandlerEnd)) return true; } return false; } bool FitsInSmallExceptionClause(Instruction start, Instruction end) { uint offs1 = GetOffset2(start); uint offs2 = GetOffset2(end); if (offs2 < offs1) return false; return offs1 <= ushort.MaxValue && offs2 - offs1 <= byte.MaxValue; } uint GetOffset2(Instruction instr) { if (instr == null) return codeSize; return GetOffset(instr); } void WriteFatExceptionClauses(BinaryWriter writer) { const int maxExceptionHandlers = (0x00FFFFFF - 4) / 24; int numExceptionHandlers = exceptionHandlers.Count; if (numExceptionHandlers > maxExceptionHandlers) { Error("Too many exception handlers"); numExceptionHandlers = maxExceptionHandlers; } writer.Write((((uint)numExceptionHandlers * 24 + 4) << 8) | 0x41); for (int i = 0; i < numExceptionHandlers; i++) { var eh = exceptionHandlers[i]; uint offs1, offs2; writer.Write((uint)eh.HandlerType); offs1 = GetOffset2(eh.TryStart); offs2 = GetOffset2(eh.TryEnd); if (offs2 <= offs1) Error("Exception handler: TryEnd <= TryStart"); writer.Write(offs1); writer.Write(offs2 - offs1); offs1 = GetOffset2(eh.HandlerStart); offs2 = GetOffset2(eh.HandlerEnd); if (offs2 <= offs1) Error("Exception handler: HandlerEnd <= HandlerStart"); writer.Write(offs1); writer.Write(offs2 - offs1); if (eh.HandlerType == ExceptionHandlerType.Catch) writer.Write(helper.GetToken(eh.CatchType).Raw); else if (eh.HandlerType == ExceptionHandlerType.Filter) writer.Write(GetOffset2(eh.FilterStart)); else writer.Write(0); } } void WriteSmallExceptionClauses(BinaryWriter writer) { const int maxExceptionHandlers = (0xFF - 4) / 12; int numExceptionHandlers = exceptionHandlers.Count; if (numExceptionHandlers > maxExceptionHandlers) { Error("Too many exception handlers"); numExceptionHandlers = maxExceptionHandlers; } writer.Write((((uint)numExceptionHandlers * 12 + 4) << 8) | 1); for (int i = 0; i < numExceptionHandlers; i++) { var eh = exceptionHandlers[i]; uint offs1, offs2; writer.Write((ushort)eh.HandlerType); offs1 = GetOffset2(eh.TryStart); offs2 = GetOffset2(eh.TryEnd); if (offs2 <= offs1) Error("Exception handler: TryEnd <= TryStart"); writer.Write((ushort)offs1); writer.Write((byte)(offs2 - offs1)); offs1 = GetOffset2(eh.HandlerStart); offs2 = GetOffset2(eh.HandlerEnd); if (offs2 <= offs1) Error("Exception handler: HandlerEnd <= HandlerStart"); writer.Write((ushort)offs1); writer.Write((byte)(offs2 - offs1)); if (eh.HandlerType == ExceptionHandlerType.Catch) writer.Write(helper.GetToken(eh.CatchType).Raw); else if (eh.HandlerType == ExceptionHandlerType.Filter) writer.Write(GetOffset2(eh.FilterStart)); else writer.Write(0); } } /// protected override void ErrorImpl(string message) { helper.Error(message); } /// protected override void WriteInlineField(BinaryWriter writer, Instruction instr) { writer.Write(helper.GetToken(instr.Operand).Raw); } /// protected override void WriteInlineMethod(BinaryWriter writer, Instruction instr) { writer.Write(helper.GetToken(instr.Operand).Raw); } /// protected override void WriteInlineSig(BinaryWriter writer, Instruction instr) { writer.Write(helper.GetToken(instr.Operand).Raw); } /// protected override void WriteInlineString(BinaryWriter writer, Instruction instr) { writer.Write(helper.GetToken(instr.Operand).Raw); } /// protected override void WriteInlineTok(BinaryWriter writer, Instruction instr) { writer.Write(helper.GetToken(instr.Operand).Raw); } /// protected override void WriteInlineType(BinaryWriter writer, Instruction instr) { writer.Write(helper.GetToken(instr.Operand).Raw); } } } dnlib-2.1_VS2010/src/DotNet/Writer/MethodBodyWriterBase.cs000066400000000000000000000355721325033663500232160ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.IO; using dnlib.DotNet.Emit; namespace dnlib.DotNet.Writer { /// /// Base class of all CIL method body writers /// public abstract class MethodBodyWriterBase { /// protected IList instructions; /// protected IList exceptionHandlers; readonly Dictionary offsets = new Dictionary(); uint firstInstructionOffset; int errors; MaxStackCalculator maxStackCalculator = MaxStackCalculator.Create(); /// /// true if there was at least one error /// public bool ErrorDetected { get { return errors > 0; } } internal MethodBodyWriterBase() { } /// /// Constructor /// /// All instructions /// All exception handlers protected MethodBodyWriterBase(IList instructions, IList exceptionHandlers) { this.instructions = instructions; this.exceptionHandlers = exceptionHandlers; } internal void Reset(IList instructions, IList exceptionHandlers) { this.instructions = instructions; this.exceptionHandlers = exceptionHandlers; offsets.Clear(); firstInstructionOffset = 0; errors = 0; } /// /// Called when an error is detected (eg. a null pointer). The error can be /// ignored but the method won't be valid. /// /// Error message protected void Error(string message) { errors++; ErrorImpl(message); } /// /// Called when an error is detected (eg. a null pointer). The error can be /// ignored but the method won't be valid. /// /// Error message protected virtual void ErrorImpl(string message) { } /// /// Gets max stack value /// protected uint GetMaxStack() { if (instructions.Count == 0) return 0; uint maxStack; maxStackCalculator.Reset(instructions, exceptionHandlers); if (!maxStackCalculator.Calculate(out maxStack)) { Error("Error calculating max stack value. If the method's obfuscated, set CilBody.KeepOldMaxStack or MetaDataOptions.Flags (KeepOldMaxStack, global option) to ignore this error. Otherwise fix your generated CIL code so it conforms to the ECMA standard."); maxStack += 8; } return maxStack; } /// /// Gets the offset of an instruction /// /// The instruction /// The offset or 0 if is null or not /// present in the list of all instructions. protected uint GetOffset(Instruction instr) { if (instr == null) { Error("Instruction is null"); return 0; } uint offset; if (offsets.TryGetValue(instr, out offset)) return offset; Error("Found some other method's instruction or a removed instruction. You probably removed an instruction that is the target of a branch instruction or an instruction that's the first/last instruction in an exception handler."); return 0; } /// /// Initializes instruction offsets and returns the total code size /// /// Size of code protected uint InitializeInstructionOffsets() { uint offset = 0; foreach (var instr in instructions) { if (instr == null) continue; offsets[instr] = offset; offset += GetSizeOfInstruction(instr); } return offset; } /// /// Gets the size of an instruction /// /// The instruction /// Size of the instruction in bytes protected virtual uint GetSizeOfInstruction(Instruction instr) { return (uint)instr.GetSize(); } /// /// Writes all instructions to at its current offset /// /// The instruction writer /// Number of bytes written protected uint WriteInstructions(BinaryWriter writer) { firstInstructionOffset = (uint)writer.BaseStream.Position; foreach (var instr in instructions) { if (instr == null) continue; WriteInstruction(writer, instr); } return ToInstructionOffset(writer); } /// /// Gets the current offset in the instruction stream. This offset is relative to /// the first written instruction. /// /// The instruction writer /// Current offset, relative to the first written instruction protected uint ToInstructionOffset(BinaryWriter writer) { return (uint)writer.BaseStream.Position - firstInstructionOffset; } /// /// Writes an instruction /// /// The instruction writer /// The instruction protected virtual void WriteInstruction(BinaryWriter writer, Instruction instr) { WriteOpCode(writer, instr); WriteOperand(writer, instr); } /// /// Writes an instruction's opcode /// /// The instruction writer /// The instruction protected virtual void WriteOpCode(BinaryWriter writer, Instruction instr) { var code = instr.OpCode.Code; if ((ushort)code <= 0xFF) writer.Write((byte)code); else if (((ushort)code >> 8) == 0xFE) { writer.Write((byte)((ushort)code >> 8)); writer.Write((byte)code); } else if (code == Code.UNKNOWN1) writer.Write((byte)Code.Nop); else if (code == Code.UNKNOWN2) writer.Write((ushort)(((ushort)Code.Nop << 8) | Code.Nop)); else { Error("Unknown instruction"); writer.Write((byte)Code.Nop); } } /// /// Writes an instruction's operand /// /// The instruction writer /// The instruction protected virtual void WriteOperand(BinaryWriter writer, Instruction instr) { switch (instr.OpCode.OperandType) { case OperandType.InlineBrTarget: WriteInlineBrTarget(writer, instr); break; case OperandType.InlineField: WriteInlineField(writer, instr); break; case OperandType.InlineI: WriteInlineI(writer, instr); break; case OperandType.InlineI8: WriteInlineI8(writer, instr); break; case OperandType.InlineMethod: WriteInlineMethod(writer, instr); break; case OperandType.InlineNone: WriteInlineNone(writer, instr); break; case OperandType.InlinePhi: WriteInlinePhi(writer, instr); break; case OperandType.InlineR: WriteInlineR(writer, instr); break; case OperandType.InlineSig: WriteInlineSig(writer, instr); break; case OperandType.InlineString: WriteInlineString(writer, instr); break; case OperandType.InlineSwitch: WriteInlineSwitch(writer, instr); break; case OperandType.InlineTok: WriteInlineTok(writer, instr); break; case OperandType.InlineType: WriteInlineType(writer, instr); break; case OperandType.InlineVar: WriteInlineVar(writer, instr); break; case OperandType.ShortInlineBrTarget: WriteShortInlineBrTarget(writer, instr); break; case OperandType.ShortInlineI: WriteShortInlineI(writer, instr); break; case OperandType.ShortInlineR: WriteShortInlineR(writer, instr); break; case OperandType.ShortInlineVar: WriteShortInlineVar(writer, instr); break; default: Error("Unknown operand type"); break; } } /// /// Writes an operand /// /// Instruction writer /// Instruction protected virtual void WriteInlineBrTarget(BinaryWriter writer, Instruction instr) { uint displ = GetOffset(instr.Operand as Instruction) - (ToInstructionOffset(writer) + 4); writer.Write(displ); } /// /// Writes an operand /// /// Instruction writer /// Instruction protected abstract void WriteInlineField(BinaryWriter writer, Instruction instr); /// /// Writes an operand /// /// Instruction writer /// Instruction protected virtual void WriteInlineI(BinaryWriter writer, Instruction instr) { if (instr.Operand is int) writer.Write((int)instr.Operand); else { Error("Operand is not an Int32"); writer.Write(0); } } /// /// Writes an operand /// /// Instruction writer /// Instruction protected virtual void WriteInlineI8(BinaryWriter writer, Instruction instr) { if (instr.Operand is long) writer.Write((long)instr.Operand); else { Error("Operand is not an Int64"); writer.Write(0L); } } /// /// Writes an operand /// /// Instruction writer /// Instruction protected abstract void WriteInlineMethod(BinaryWriter writer, Instruction instr); /// /// Writes an operand /// /// Instruction writer /// Instruction protected virtual void WriteInlineNone(BinaryWriter writer, Instruction instr) { } /// /// Writes an operand /// /// Instruction writer /// Instruction protected virtual void WriteInlinePhi(BinaryWriter writer, Instruction instr) { } /// /// Writes an operand /// /// Instruction writer /// Instruction protected virtual void WriteInlineR(BinaryWriter writer, Instruction instr) { if (instr.Operand is double) writer.Write((double)instr.Operand); else { Error("Operand is not a Double"); writer.Write(0D); } } /// /// Writes an operand /// /// Instruction writer /// Instruction protected abstract void WriteInlineSig(BinaryWriter writer, Instruction instr); /// /// Writes an operand /// /// Instruction writer /// Instruction protected abstract void WriteInlineString(BinaryWriter writer, Instruction instr); /// /// Writes an operand /// /// Instruction writer /// Instruction protected virtual void WriteInlineSwitch(BinaryWriter writer, Instruction instr) { var targets = instr.Operand as IList; if (targets == null) { Error("switch operand is not a list of instructions"); writer.Write(0); } else { uint offsetAfter = (uint)(ToInstructionOffset(writer) + 4 + targets.Count * 4); writer.Write(targets.Count); foreach (var target in targets) writer.Write(GetOffset(target) - offsetAfter); } } /// /// Writes an operand /// /// Instruction writer /// Instruction protected abstract void WriteInlineTok(BinaryWriter writer, Instruction instr); /// /// Writes an operand /// /// Instruction writer /// Instruction protected abstract void WriteInlineType(BinaryWriter writer, Instruction instr); /// /// Writes an operand /// /// Instruction writer /// Instruction protected virtual void WriteInlineVar(BinaryWriter writer, Instruction instr) { var variable = instr.Operand as IVariable; if (variable == null) { Error("Operand is not a local/arg"); writer.Write((ushort)0); } else if (ushort.MinValue <= variable.Index && variable.Index <= ushort.MaxValue) writer.Write((ushort)variable.Index); else { Error("Local/arg index doesn't fit in a UInt16"); writer.Write((ushort)0); } } /// /// Writes a operand /// /// Instruction writer /// Instruction protected virtual void WriteShortInlineBrTarget(BinaryWriter writer, Instruction instr) { int displ = (int)(GetOffset(instr.Operand as Instruction) - (ToInstructionOffset(writer) + 1)); if (sbyte.MinValue <= displ && displ <= sbyte.MaxValue) writer.Write((sbyte)displ); else { Error("Target instruction is too far away for a short branch. Use the long branch or call CilBody.SimplifyBranches() and CilBody.OptimizeBranches()"); writer.Write((byte)0); } } /// /// Writes a operand /// /// Instruction writer /// Instruction protected virtual void WriteShortInlineI(BinaryWriter writer, Instruction instr) { if (instr.Operand is sbyte) writer.Write((sbyte)instr.Operand); else if (instr.Operand is byte) writer.Write((byte)instr.Operand); else { Error("Operand is not a Byte or a SByte"); writer.Write((byte)0); } } /// /// Writes a operand /// /// Instruction writer /// Instruction protected virtual void WriteShortInlineR(BinaryWriter writer, Instruction instr) { if (instr.Operand is float) writer.Write((float)instr.Operand); else { Error("Operand is not a Single"); writer.Write(0F); } } /// /// Writes a operand /// /// Instruction writer /// Instruction protected virtual void WriteShortInlineVar(BinaryWriter writer, Instruction instr) { var variable = instr.Operand as IVariable; if (variable == null) { Error("Operand is not a local/arg"); writer.Write((byte)0); } else if (byte.MinValue <= variable.Index && variable.Index <= byte.MaxValue) writer.Write((byte)variable.Index); else { Error("Local/arg index doesn't fit in a Byte. Use the longer ldloc/ldarg/stloc/starg instruction."); writer.Write((byte)0); } } } } dnlib-2.1_VS2010/src/DotNet/Writer/ModuleWriter.cs000066400000000000000000000246161325033663500216070ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.IO; using dnlib.DotNet.MD; using dnlib.PE; using dnlib.W32Resources; namespace dnlib.DotNet.Writer { /// /// options /// public sealed class ModuleWriterOptions : ModuleWriterOptionsBase { /// /// Default constructor /// public ModuleWriterOptions() { } /// /// Constructor /// /// The module public ModuleWriterOptions(ModuleDef module) : this(module, null) { } /// /// Constructor /// /// The module /// Module writer listener public ModuleWriterOptions(ModuleDef module, IModuleWriterListener listener) : base(module, listener) { } } /// /// Writes a .NET PE file. See also /// public sealed class ModuleWriter : ModuleWriterBase { const uint DEFAULT_RELOC_ALIGNMENT = 4; readonly ModuleDef module; ModuleWriterOptions options; List sections; PESection textSection; PESection sdataSection; PESection rsrcSection; PESection relocSection; PEHeaders peHeaders; ImportAddressTable importAddressTable; ImageCor20Header imageCor20Header; ImportDirectory importDirectory; StartupStub startupStub; RelocDirectory relocDirectory; ManagedExportsWriter managedExportsWriter; bool needStartupStub; /// public override ModuleDef Module { get { return module; } } /// public override ModuleWriterOptionsBase TheOptions { get { return Options; } } /// /// Gets/sets the writer options. This is never null /// public ModuleWriterOptions Options { get { return options ?? (options = new ModuleWriterOptions(module)); } set { options = value; } } /// /// Gets all s /// public override List Sections { get { return sections; } } /// /// Gets the .text section /// public override PESection TextSection { get { return textSection; } } /// /// Gets the .sdata section /// internal PESection SdataSection { get { return sdataSection; } } /// /// Gets the .rsrc section or null if none /// public override PESection RsrcSection { get { return rsrcSection; } } /// /// Gets the .reloc section /// public PESection RelocSection { get { return relocSection; } } /// /// Gets the PE headers /// public PEHeaders PEHeaders { get { return peHeaders; } } /// /// Gets the IAT or null if there's none /// public ImportAddressTable ImportAddressTable { get { return importAddressTable; } } /// /// Gets the .NET header /// public ImageCor20Header ImageCor20Header { get { return imageCor20Header; } } /// /// Gets the import directory or null if there's none /// public ImportDirectory ImportDirectory { get { return importDirectory; } } /// /// Gets the startup stub or null if there's none /// public StartupStub StartupStub { get { return startupStub; } } /// /// Gets the reloc directory or null if there's none /// public RelocDirectory RelocDirectory { get { return relocDirectory; } } /// /// Constructor /// /// The module public ModuleWriter(ModuleDef module) : this(module, null) { } /// /// Constructor /// /// The module /// Options or null public ModuleWriter(ModuleDef module, ModuleWriterOptions options) { this.module = module; this.options = options; } /// protected override long WriteImpl() { Initialize(); metaData.CreateTables(); return WriteFile(); } void Initialize() { CreateSections(); Listener.OnWriterEvent(this, ModuleWriterEvent.PESectionsCreated); CreateChunks(); Listener.OnWriterEvent(this, ModuleWriterEvent.ChunksCreated); AddChunksToSections(); Listener.OnWriterEvent(this, ModuleWriterEvent.ChunksAddedToSections); } /// protected override Win32Resources GetWin32Resources() { return Options.Win32Resources ?? module.Win32Resources; } void CreateSections() { sections = new List(); sections.Add(textSection = new PESection(".text", 0x60000020)); sections.Add(sdataSection = new PESection(".sdata", 0xC0000040)); if (GetWin32Resources() != null) sections.Add(rsrcSection = new PESection(".rsrc", 0x40000040)); // Should be last so any data in a previous section can add relocations sections.Add(relocSection = new PESection(".reloc", 0x42000040)); } void CreateChunks() { peHeaders = new PEHeaders(Options.PEHeadersOptions); var machine = Options.PEHeadersOptions.Machine ?? Machine.I386; bool is64bit = machine == Machine.AMD64 || machine == Machine.IA64 || machine == Machine.ARM64; relocDirectory = new RelocDirectory(machine); if (machine == Machine.I386) needStartupStub = true; importAddressTable = new ImportAddressTable(is64bit); importDirectory = new ImportDirectory(is64bit); startupStub = new StartupStub(relocDirectory, machine, (format, args) => Error(format, args)); CreateStrongNameSignature(); imageCor20Header = new ImageCor20Header(Options.Cor20HeaderOptions); CreateMetaDataChunks(module); managedExportsWriter = new ManagedExportsWriter(UTF8String.ToSystemStringOrEmpty(module.Name), machine, relocDirectory, metaData, peHeaders, (format, args) => Error(format, args)); CreateDebugDirectory(); importDirectory.IsExeFile = Options.IsExeFile; peHeaders.IsExeFile = Options.IsExeFile; } void AddChunksToSections() { var machine = Options.PEHeadersOptions.Machine ?? Machine.I386; bool is64bit = machine == Machine.AMD64 || machine == Machine.IA64 || machine == Machine.ARM64; uint pointerAlignment = is64bit ? 8U : 4; textSection.Add(importAddressTable, pointerAlignment); textSection.Add(imageCor20Header, DEFAULT_COR20HEADER_ALIGNMENT); textSection.Add(strongNameSignature, DEFAULT_STRONGNAMESIG_ALIGNMENT); managedExportsWriter.AddTextChunks(textSection); textSection.Add(constants, DEFAULT_CONSTANTS_ALIGNMENT); textSection.Add(methodBodies, DEFAULT_METHODBODIES_ALIGNMENT); textSection.Add(netResources, DEFAULT_NETRESOURCES_ALIGNMENT); textSection.Add(metaData, DEFAULT_METADATA_ALIGNMENT); textSection.Add(debugDirectory, DebugDirectory.DEFAULT_DEBUGDIRECTORY_ALIGNMENT); textSection.Add(importDirectory, pointerAlignment); textSection.Add(startupStub, startupStub.Alignment); managedExportsWriter.AddSdataChunks(sdataSection); if (GetWin32Resources() != null) rsrcSection.Add(win32Resources, DEFAULT_WIN32_RESOURCES_ALIGNMENT); relocSection.Add(relocDirectory, DEFAULT_RELOC_ALIGNMENT); } long WriteFile() { managedExportsWriter.AddExportedMethods(metaData.ExportedMethods, GetTimeDateStamp()); if (managedExportsWriter.HasExports) needStartupStub = true; Listener.OnWriterEvent(this, ModuleWriterEvent.BeginWritePdb); WritePdbFile(); Listener.OnWriterEvent(this, ModuleWriterEvent.EndWritePdb); Listener.OnWriterEvent(this, ModuleWriterEvent.BeginCalculateRvasAndFileOffsets); var chunks = new List(); chunks.Add(peHeaders); if (!managedExportsWriter.HasExports) sections.Remove(sdataSection); if (!(relocDirectory.NeedsRelocSection || managedExportsWriter.HasExports || needStartupStub)) sections.Remove(relocSection); importAddressTable.Enable = needStartupStub; importDirectory.Enable = needStartupStub; startupStub.Enable = needStartupStub; foreach (var section in sections) chunks.Add(section); peHeaders.PESections = sections; CalculateRvasAndFileOffsets(chunks, 0, 0, peHeaders.FileAlignment, peHeaders.SectionAlignment); Listener.OnWriterEvent(this, ModuleWriterEvent.EndCalculateRvasAndFileOffsets); InitializeChunkProperties(); Listener.OnWriterEvent(this, ModuleWriterEvent.BeginWriteChunks); var writer = new BinaryWriter(destStream); WriteChunks(writer, chunks, 0, peHeaders.FileAlignment); long imageLength = writer.BaseStream.Position - destStreamBaseOffset; Listener.OnWriterEvent(this, ModuleWriterEvent.EndWriteChunks); Listener.OnWriterEvent(this, ModuleWriterEvent.BeginStrongNameSign); if (Options.StrongNameKey != null) StrongNameSign((long)strongNameSignature.FileOffset); Listener.OnWriterEvent(this, ModuleWriterEvent.EndStrongNameSign); Listener.OnWriterEvent(this, ModuleWriterEvent.BeginWritePEChecksum); if (Options.AddCheckSum) peHeaders.WriteCheckSum(writer, imageLength); Listener.OnWriterEvent(this, ModuleWriterEvent.EndWritePEChecksum); return imageLength; } void InitializeChunkProperties() { Options.Cor20HeaderOptions.EntryPoint = GetEntryPoint(); importAddressTable.ImportDirectory = importDirectory; importDirectory.ImportAddressTable = importAddressTable; startupStub.ImportDirectory = importDirectory; startupStub.PEHeaders = peHeaders; peHeaders.StartupStub = startupStub; peHeaders.ImageCor20Header = imageCor20Header; peHeaders.ImportAddressTable = importAddressTable; peHeaders.ImportDirectory = importDirectory; peHeaders.Win32Resources = win32Resources; peHeaders.RelocDirectory = relocDirectory; peHeaders.DebugDirectory = debugDirectory; imageCor20Header.MetaData = metaData; imageCor20Header.NetResources = netResources; imageCor20Header.StrongNameSignature = strongNameSignature; managedExportsWriter.InitializeChunkProperties(); } uint GetEntryPoint() { var methodEntryPoint = module.ManagedEntryPoint as MethodDef; if (methodEntryPoint != null) return new MDToken(Table.Method, metaData.GetRid(methodEntryPoint)).Raw; var fileEntryPoint = module.ManagedEntryPoint as FileDef; if (fileEntryPoint != null) return new MDToken(Table.File, metaData.GetRid(fileEntryPoint)).Raw; uint nativeEntryPoint = (uint)module.NativeEntryPoint; if (nativeEntryPoint != 0) return nativeEntryPoint; return 0; } } } dnlib-2.1_VS2010/src/DotNet/Writer/ModuleWriterBase.cs000066400000000000000000001127371325033663500224040ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.IO; using dnlib.DotNet.Pdb; using dnlib.PE; using dnlib.W32Resources; using dnlib.DotNet.MD; using System.Diagnostics; using dnlib.DotNet.Pdb.WindowsPdb; using System.Text; using System.IO.Compression; namespace dnlib.DotNet.Writer { /// /// Common module writer options base class /// public class ModuleWriterOptionsBase { IModuleWriterListener listener; PEHeadersOptions peHeadersOptions; Cor20HeaderOptions cor20HeaderOptions; MetaDataOptions metaDataOptions; ILogger logger; ILogger metaDataLogger; Win32Resources win32Resources; StrongNameKey strongNameKey; StrongNamePublicKey strongNamePublicKey; bool delaySign; /// /// Gets/sets the listener /// public IModuleWriterListener Listener { get { return listener; } set { listener = value; } } /// /// Gets/sets the logger. If this is null, any errors result in a /// being thrown. To disable this behavior, either /// create your own logger or use . /// public ILogger Logger { get { return logger; } set { logger = value; } } /// /// Gets/sets the writer logger. If this is null, use /// . /// public ILogger MetaDataLogger { get { return metaDataLogger; } set { metaDataLogger = value; } } /// /// Gets/sets the options. This is never null. /// public PEHeadersOptions PEHeadersOptions { get { return peHeadersOptions ?? (peHeadersOptions = new PEHeadersOptions()); } set { peHeadersOptions = value; } } /// /// Gets/sets the options. This is never null. /// public Cor20HeaderOptions Cor20HeaderOptions { get { return cor20HeaderOptions ?? (cor20HeaderOptions = new Cor20HeaderOptions()); } set { cor20HeaderOptions = value; } } /// /// Gets/sets the options. This is never null. /// public MetaDataOptions MetaDataOptions { get { return metaDataOptions ?? (metaDataOptions = new MetaDataOptions()); } set { metaDataOptions = value; } } /// /// Gets/sets the Win32 resources. If this is null, use the module's /// Win32 resources if any. /// public Win32Resources Win32Resources { get { return win32Resources; } set { win32Resources = value; } } /// /// true to delay sign the assembly. Initialize to the /// public key to use, and don't initialize . To generate the /// public key from your strong name key file, execute sn -p mykey.snk mypublickey.snk /// public bool DelaySign { get { return delaySign; } set { delaySign = value; } } /// /// Gets/sets the strong name key. When you enhance strong name sign an assembly, /// this instance's HashAlgorithm must be initialized to its public key's HashAlgorithm. /// You should call /// to initialize this property if you use normal strong name signing. /// You should call /// or /// to initialize this property if you use enhanced strong name signing. /// public StrongNameKey StrongNameKey { get { return strongNameKey; } set { strongNameKey = value; } } /// /// Gets/sets the new public key that should be used. If this is null, use /// the public key generated from . If it is also null, /// use the module's Assembly's public key. /// You should call /// or /// to initialize this property if you use enhanced strong name signing. /// public StrongNamePublicKey StrongNamePublicKey { get { return strongNamePublicKey; } set { strongNamePublicKey = value; } } /// /// true if method bodies can be shared (two or more method bodies can share the /// same RVA), false if method bodies can't be shared. Don't enable it if there /// must be a 1:1 relationship with method bodies and their RVAs. /// public bool ShareMethodBodies { get; set; } /// /// true if the PE header CheckSum field should be updated, false if the /// CheckSum field isn't updated. /// public bool AddCheckSum { get; set; } /// /// true if it's a 64-bit module, false if it's a 32-bit or AnyCPU module. /// public bool Is64Bit { get { if (!PEHeadersOptions.Machine.HasValue) return false; return PEHeadersOptions.Machine == Machine.IA64 || PEHeadersOptions.Machine == Machine.AMD64 || PEHeadersOptions.Machine == Machine.ARM64; } } /// /// Gets/sets the module kind /// public ModuleKind ModuleKind { get; set; } /// /// true if it should be written as an EXE file, false if it should be /// written as a DLL file. /// public bool IsExeFile { get { return ModuleKind != ModuleKind.Dll && ModuleKind != ModuleKind.NetModule; } } /// /// Set it to true to enable writing a PDB file. Default is false (a PDB file /// won't be written to disk). /// public bool WritePdb { get; set; } /// /// PDB file name. If it's null a PDB file with the same name as the output assembly /// will be created but with a PDB extension. must be true or /// this property is ignored. /// public string PdbFileName { get; set; } /// /// PDB stream. If this is initialized, then you should also set /// to the name of the PDB file since the file name must be written to the PE debug directory. /// must be true or this property is ignored. /// public Stream PdbStream { get; set; } /// /// GUID used by some PDB writers, eg. portable PDB writer. It's initialized to a random GUID. /// public Guid PdbGuid { get; set; } /// /// Default constructor /// protected ModuleWriterOptionsBase() { ShareMethodBodies = true; ModuleKind = ModuleKind.Windows; PdbGuid = Guid.NewGuid(); } /// /// Constructor /// /// The module protected ModuleWriterOptionsBase(ModuleDef module) : this(module, null) { } /// /// Constructor /// /// The module /// Module writer listener protected ModuleWriterOptionsBase(ModuleDef module, IModuleWriterListener listener) { this.listener = listener; PdbGuid = Guid.NewGuid(); ShareMethodBodies = true; MetaDataOptions.MetaDataHeaderOptions.VersionString = module.RuntimeVersion; ModuleKind = module.Kind; PEHeadersOptions.Machine = module.Machine; PEHeadersOptions.Characteristics = module.Characteristics; PEHeadersOptions.DllCharacteristics = module.DllCharacteristics; if (module.Kind == ModuleKind.Windows) PEHeadersOptions.Subsystem = Subsystem.WindowsGui; else PEHeadersOptions.Subsystem = Subsystem.WindowsCui; PEHeadersOptions.NumberOfRvaAndSizes = 0x10; Cor20HeaderOptions.Flags = module.Cor20HeaderFlags; if (module.Assembly != null && !PublicKeyBase.IsNullOrEmpty2(module.Assembly.PublicKey)) Cor20HeaderOptions.Flags |= ComImageFlags.StrongNameSigned; if (module.Cor20HeaderRuntimeVersion != null) { Cor20HeaderOptions.MajorRuntimeVersion = (ushort)(module.Cor20HeaderRuntimeVersion.Value >> 16); Cor20HeaderOptions.MinorRuntimeVersion = (ushort)module.Cor20HeaderRuntimeVersion.Value; } else if (module.IsClr1x) { Cor20HeaderOptions.MajorRuntimeVersion = 2; Cor20HeaderOptions.MinorRuntimeVersion = 0; } else { Cor20HeaderOptions.MajorRuntimeVersion = 2; Cor20HeaderOptions.MinorRuntimeVersion = 5; } if (module.TablesHeaderVersion != null) { MetaDataOptions.TablesHeapOptions.MajorVersion = (byte)(module.TablesHeaderVersion.Value >> 8); MetaDataOptions.TablesHeapOptions.MinorVersion = (byte)module.TablesHeaderVersion.Value; } else if (module.IsClr1x) { // Generics aren't supported MetaDataOptions.TablesHeapOptions.MajorVersion = 1; MetaDataOptions.TablesHeapOptions.MinorVersion = 0; } else { // Generics are supported MetaDataOptions.TablesHeapOptions.MajorVersion = 2; MetaDataOptions.TablesHeapOptions.MinorVersion = 0; } // Some tools crash if #GUID is missing so always create it by default MetaDataOptions.Flags |= MetaDataFlags.AlwaysCreateGuidHeap; var modDefMD = module as ModuleDefMD; if (modDefMD != null) { var ntHeaders = modDefMD.MetaData.PEImage.ImageNTHeaders; PEHeadersOptions.TimeDateStamp = ntHeaders.FileHeader.TimeDateStamp; PEHeadersOptions.MajorLinkerVersion = ntHeaders.OptionalHeader.MajorLinkerVersion; PEHeadersOptions.MinorLinkerVersion = ntHeaders.OptionalHeader.MinorLinkerVersion; PEHeadersOptions.ImageBase = ntHeaders.OptionalHeader.ImageBase; PEHeadersOptions.MajorOperatingSystemVersion = ntHeaders.OptionalHeader.MajorOperatingSystemVersion; PEHeadersOptions.MinorOperatingSystemVersion = ntHeaders.OptionalHeader.MinorOperatingSystemVersion; PEHeadersOptions.MajorImageVersion = ntHeaders.OptionalHeader.MajorImageVersion; PEHeadersOptions.MinorImageVersion = ntHeaders.OptionalHeader.MinorImageVersion; PEHeadersOptions.MajorSubsystemVersion = ntHeaders.OptionalHeader.MajorSubsystemVersion; PEHeadersOptions.MinorSubsystemVersion = ntHeaders.OptionalHeader.MinorSubsystemVersion; PEHeadersOptions.Win32VersionValue = ntHeaders.OptionalHeader.Win32VersionValue; AddCheckSum = ntHeaders.OptionalHeader.CheckSum != 0; } if (Is64Bit) { PEHeadersOptions.Characteristics &= ~Characteristics._32BitMachine; PEHeadersOptions.Characteristics |= Characteristics.LargeAddressAware; } else if (modDefMD == null) PEHeadersOptions.Characteristics |= Characteristics._32BitMachine; } /// /// Initializes and /// for normal strong name signing. /// /// Module /// Signature strong name key pair public void InitializeStrongNameSigning(ModuleDef module, StrongNameKey signatureKey) { StrongNameKey = signatureKey; StrongNamePublicKey = null; if (module.Assembly != null) module.Assembly.CustomAttributes.RemoveAll("System.Reflection.AssemblySignatureKeyAttribute"); } /// /// Initializes and /// for enhanced strong name signing (without key migration). See /// http://msdn.microsoft.com/en-us/library/hh415055.aspx /// /// Module /// Signature strong name key pair /// Signature public key public void InitializeEnhancedStrongNameSigning(ModuleDef module, StrongNameKey signatureKey, StrongNamePublicKey signaturePubKey) { InitializeStrongNameSigning(module, signatureKey); StrongNameKey.HashAlgorithm = signaturePubKey.HashAlgorithm; } /// /// Initializes and /// for enhanced strong name signing (with key migration). See /// http://msdn.microsoft.com/en-us/library/hh415055.aspx /// /// Module /// Signature strong name key pair /// Signature public key /// Identity strong name key pair /// Identity public key public void InitializeEnhancedStrongNameSigning(ModuleDef module, StrongNameKey signatureKey, StrongNamePublicKey signaturePubKey, StrongNameKey identityKey, StrongNamePublicKey identityPubKey) { StrongNameKey = signatureKey; StrongNameKey.HashAlgorithm = signaturePubKey.HashAlgorithm; StrongNamePublicKey = identityPubKey; if (module.Assembly != null) module.Assembly.UpdateOrCreateAssemblySignatureKeyAttribute(identityPubKey, identityKey, signaturePubKey); } } /// /// Module writer base class /// public abstract class ModuleWriterBase : IMetaDataListener, ILogger { /// Default alignment of all constants protected internal const uint DEFAULT_CONSTANTS_ALIGNMENT = 8; /// Default alignment of all method bodies protected const uint DEFAULT_METHODBODIES_ALIGNMENT = 4; /// Default alignment of all .NET resources protected const uint DEFAULT_NETRESOURCES_ALIGNMENT = 8; /// Default alignment of the .NET metadata protected const uint DEFAULT_METADATA_ALIGNMENT = 4; /// Default Win32 resources alignment protected internal const uint DEFAULT_WIN32_RESOURCES_ALIGNMENT = 8; /// Default strong name signature alignment protected const uint DEFAULT_STRONGNAMESIG_ALIGNMENT = 16; /// Default COR20 header alignment protected const uint DEFAULT_COR20HEADER_ALIGNMENT = 4; /// See protected Stream destStream; /// See protected UniqueChunkList constants; /// See protected MethodBodyChunks methodBodies; /// See protected NetResources netResources; /// See protected MetaData metaData; /// See protected Win32ResourcesChunk win32Resources; /// Offset where the module is written. Usually 0. protected long destStreamBaseOffset; IModuleWriterListener listener; /// Debug directory protected DebugDirectory debugDirectory; string createdPdbFileName; /// /// Strong name signature /// protected StrongNameSignature strongNameSignature; /// /// Returns the module writer options /// public abstract ModuleWriterOptionsBase TheOptions { get; } /// /// Gets/sets the module writer listener /// protected IModuleWriterListener Listener { get { return listener ?? DummyModuleWriterListener.Instance; } set { listener = value; } } /// /// Gets the destination stream /// public Stream DestinationStream { get { return destStream; } } /// /// Gets the constants /// public UniqueChunkList Constants { get { return constants; } } /// /// Gets the method bodies /// public MethodBodyChunks MethodBodies { get { return methodBodies; } } /// /// Gets the .NET resources /// public NetResources NetResources { get { return netResources; } } /// /// Gets the .NET metadata /// public MetaData MetaData { get { return metaData; } } /// /// Gets the Win32 resources or null if there's none /// public Win32ResourcesChunk Win32Resources { get { return win32Resources; } } /// /// Gets the strong name signature or null if there's none /// public StrongNameSignature StrongNameSignature { get { return strongNameSignature; } } /// /// Gets all s /// public abstract List Sections { get; } /// /// Gets the .text section /// public abstract PESection TextSection { get; } /// /// Gets the .rsrc section or null if there's none /// public abstract PESection RsrcSection { get; } /// /// Gets the debug directory or null if there's none /// public DebugDirectory DebugDirectory { get { return debugDirectory; } } /// /// true if this is a , false if /// this is a . /// public bool IsNativeWriter { get { return this is NativeModuleWriter; } } /// /// null if we're not writing a PDB /// PdbState pdbState; /// /// Writes the module to a file /// /// File name. The file will be truncated if it exists. public void Write(string fileName) { using (var dest = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)) { dest.SetLength(0); try { Write(dest); } catch { // Writing failed. Delete the file since it's useless. dest.Close(); DeleteFileNoThrow(fileName); throw; } } } static void DeleteFileNoThrow(string fileName) { if (string.IsNullOrEmpty(fileName)) return; try { File.Delete(fileName); } catch { } } /// /// Writes the module to a /// /// Destination stream public void Write(Stream dest) { pdbState = TheOptions.WritePdb && Module.PdbState != null ? Module.PdbState : null; if (TheOptions.DelaySign) { Debug.Assert(TheOptions.StrongNamePublicKey != null, "Options.StrongNamePublicKey must be initialized when delay signing the assembly"); Debug.Assert(TheOptions.StrongNameKey == null, "Options.StrongNameKey must be null when delay signing the assembly"); TheOptions.Cor20HeaderOptions.Flags &= ~ComImageFlags.StrongNameSigned; } else if (TheOptions.StrongNameKey != null || TheOptions.StrongNamePublicKey != null) TheOptions.Cor20HeaderOptions.Flags |= ComImageFlags.StrongNameSigned; Listener = TheOptions.Listener ?? DummyModuleWriterListener.Instance; destStream = dest; destStreamBaseOffset = destStream.Position; Listener.OnWriterEvent(this, ModuleWriterEvent.Begin); var imageLength = WriteImpl(); destStream.Position = destStreamBaseOffset + imageLength; Listener.OnWriterEvent(this, ModuleWriterEvent.End); } /// /// Returns the module that is written /// public abstract ModuleDef Module { get; } /// /// Writes the module to . and /// have been initialized when this method is called. /// /// Number of bytes written protected abstract long WriteImpl(); /// /// Creates the strong name signature if the module has one of the strong name flags /// set or wants to sign the assembly. /// protected void CreateStrongNameSignature() { if (TheOptions.DelaySign && TheOptions.StrongNamePublicKey != null) { int len = TheOptions.StrongNamePublicKey.CreatePublicKey().Length - 0x20; strongNameSignature = new StrongNameSignature(len > 0 ? len : 0x80); } else if (TheOptions.StrongNameKey != null) strongNameSignature = new StrongNameSignature(TheOptions.StrongNameKey.SignatureSize); else if (Module.Assembly != null && !PublicKeyBase.IsNullOrEmpty2(Module.Assembly.PublicKey)) { int len = Module.Assembly.PublicKey.Data.Length - 0x20; strongNameSignature = new StrongNameSignature(len > 0 ? len : 0x80); } else if (((TheOptions.Cor20HeaderOptions.Flags ?? Module.Cor20HeaderFlags) & ComImageFlags.StrongNameSigned) != 0) strongNameSignature = new StrongNameSignature(0x80); } /// /// Creates the .NET metadata chunks (constants, method bodies, .NET resources, /// the metadata, and Win32 resources) /// /// protected void CreateMetaDataChunks(ModuleDef module) { constants = new UniqueChunkList(); methodBodies = new MethodBodyChunks(TheOptions.ShareMethodBodies); netResources = new NetResources(DEFAULT_NETRESOURCES_ALIGNMENT); DebugMetaDataKind debugKind; if (pdbState != null && (pdbState.PdbFileKind == PdbFileKind.PortablePDB || pdbState.PdbFileKind == PdbFileKind.EmbeddedPortablePDB)) debugKind = DebugMetaDataKind.Standalone; else debugKind = DebugMetaDataKind.None; metaData = MetaData.Create(module, constants, methodBodies, netResources, TheOptions.MetaDataOptions, debugKind); metaData.Logger = TheOptions.MetaDataLogger ?? this; metaData.Listener = this; // StrongNamePublicKey is used if the user wants to override the assembly's // public key or when enhanced strong naming the assembly. var pk = TheOptions.StrongNamePublicKey; if (pk != null) metaData.AssemblyPublicKey = pk.CreatePublicKey(); else if (TheOptions.StrongNameKey != null) metaData.AssemblyPublicKey = TheOptions.StrongNameKey.PublicKey; var w32Resources = GetWin32Resources(); if (w32Resources != null) win32Resources = new Win32ResourcesChunk(w32Resources); } /// /// Gets the Win32 resources that should be written to the new image or null if none /// protected abstract Win32Resources GetWin32Resources(); /// /// Calculates and of all s /// /// All chunks /// Starting file offset /// Starting RVA /// File alignment /// Section alignment protected void CalculateRvasAndFileOffsets(List chunks, FileOffset offset, RVA rva, uint fileAlignment, uint sectionAlignment) { foreach (var chunk in chunks) { chunk.SetOffset(offset, rva); // If it has zero size, it's not present in the file (eg. a section that wasn't needed) if (chunk.GetVirtualSize() != 0) { offset += chunk.GetFileLength(); rva += chunk.GetVirtualSize(); offset = offset.AlignUp(fileAlignment); rva = rva.AlignUp(sectionAlignment); } } } /// /// Writes all chunks to /// /// The writer /// All chunks /// File offset of first chunk /// File alignment protected void WriteChunks(BinaryWriter writer, List chunks, FileOffset offset, uint fileAlignment) { foreach (var chunk in chunks) { chunk.VerifyWriteTo(writer); // If it has zero size, it's not present in the file (eg. a section that wasn't needed) if (chunk.GetVirtualSize() != 0) { offset += chunk.GetFileLength(); var newOffset = offset.AlignUp(fileAlignment); writer.WriteZeros((int)(newOffset - offset)); offset = newOffset; } } } /// /// Strong name sign the assembly /// /// Strong name signature offset protected void StrongNameSign(long snSigOffset) { var snSigner = new StrongNameSigner(destStream, destStreamBaseOffset); snSigner.WriteSignature(TheOptions.StrongNameKey, snSigOffset); } bool CanWritePdb() { return pdbState != null; } /// /// Creates the debug directory if a PDB file should be written /// protected void CreateDebugDirectory() { if (CanWritePdb()) debugDirectory = new DebugDirectory(); } /// /// Write the PDB file. The caller should send the PDB events before and after calling this /// method. /// protected void WritePdbFile() { if (!CanWritePdb()) return; if (debugDirectory == null) throw new InvalidOperationException("debugDirectory is null but WritePdb is true"); if (pdbState == null) { Error("TheOptions.WritePdb is true but module has no PdbState"); return; } try { switch (pdbState.PdbFileKind) { case PdbFileKind.WindowsPDB: WriteWindowsPdb(pdbState); break; case PdbFileKind.PortablePDB: WritePortablePdb(pdbState, false); break; case PdbFileKind.EmbeddedPortablePDB: WritePortablePdb(pdbState, true); break; default: Error("Invalid PDB file kind {0}", pdbState.PdbFileKind); break; } } catch { DeleteFileNoThrow(createdPdbFileName); throw; } } void WriteWindowsPdb(PdbState pdbState) { var symWriter = GetWindowsPdbSymbolWriter(); if (symWriter == null) { Error("Could not create a PDB symbol writer. A Windows OS might be required."); return; } using (var pdbWriter = new WindowsPdbWriter(symWriter, pdbState, metaData)) { pdbWriter.Logger = TheOptions.Logger; pdbWriter.Write(); IMAGE_DEBUG_DIRECTORY idd; var data = pdbWriter.GetDebugInfo(out idd); var entry = debugDirectory.Add(data); entry.DebugDirectory = idd; entry.DebugDirectory.TimeDateStamp = GetTimeDateStamp(); } } /// /// Gets the timestamp stored in the PE header /// /// protected uint GetTimeDateStamp() { var td = TheOptions.PEHeadersOptions.TimeDateStamp; if (td.HasValue) return (uint)td; TheOptions.PEHeadersOptions.TimeDateStamp = PEHeadersOptions.CreateNewTimeDateStamp(); return (uint)TheOptions.PEHeadersOptions.TimeDateStamp; } ISymbolWriter2 GetWindowsPdbSymbolWriter() { if (TheOptions.PdbStream != null) { return SymbolWriterCreator.Create(TheOptions.PdbStream, TheOptions.PdbFileName ?? GetStreamName(TheOptions.PdbStream) ?? GetDefaultPdbFileName()); } if (!string.IsNullOrEmpty(TheOptions.PdbFileName)) { createdPdbFileName = TheOptions.PdbFileName; return SymbolWriterCreator.Create(createdPdbFileName); } createdPdbFileName = GetDefaultPdbFileName(); if (createdPdbFileName == null) return null; return SymbolWriterCreator.Create(createdPdbFileName); } static string GetStreamName(Stream stream) { var fs = stream as FileStream; return fs == null ? null : fs.Name; } static string GetModuleName(ModuleDef module) { var name = module.Name ?? string.Empty; if (string.IsNullOrEmpty(name)) return null; if (name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) || name.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) || name.EndsWith(".netmodule", StringComparison.OrdinalIgnoreCase)) return name; return name + ".pdb"; } string GetDefaultPdbFileName() { var destFileName = GetStreamName(destStream) ?? GetModuleName(Module); if (string.IsNullOrEmpty(destFileName)) { Error("TheOptions.WritePdb is true but it's not possible to guess the default PDB file name. Set PdbFileName to the name of the PDB file."); return null; } return Path.ChangeExtension(destFileName, "pdb"); } void WritePortablePdb(PdbState pdbState, bool isEmbeddedPortablePdb) { bool ownsStream = false; Stream pdbStream = null; try { MemoryStream embeddedMemoryStream = null; if (isEmbeddedPortablePdb) { pdbStream = embeddedMemoryStream = new MemoryStream(); ownsStream = true; } else pdbStream = GetStandalonePortablePdbStream(out ownsStream); var pdbFilename = TheOptions.PdbFileName ?? GetStreamName(pdbStream) ?? GetDefaultPdbFileName(); if (isEmbeddedPortablePdb) pdbFilename = Path.GetFileName(pdbFilename); uint entryPointToken; if (pdbState.UserEntryPoint == null) entryPointToken = 0; else entryPointToken = new MDToken(Table.Method, metaData.GetRid(pdbState.UserEntryPoint)).Raw; var pdbId = new byte[20]; var pdbIdWriter = new BinaryWriter(new MemoryStream(pdbId)); var pdbGuid = TheOptions.PdbGuid; pdbIdWriter.Write(pdbGuid.ToByteArray()); pdbIdWriter.Write(GetTimeDateStamp()); Debug.Assert(pdbIdWriter.BaseStream.Position == pdbId.Length); metaData.WritePortablePdb(pdbStream, entryPointToken, pdbId); const uint age = 1; var cvEntry = debugDirectory.Add(GetCodeViewData(pdbGuid, age, pdbFilename)); cvEntry.DebugDirectory.TimeDateStamp = GetTimeDateStamp(); cvEntry.DebugDirectory.MajorVersion = PortablePdbConstants.FormatVersion; cvEntry.DebugDirectory.MinorVersion = PortablePdbConstants.PortableCodeViewVersionMagic; cvEntry.DebugDirectory.Type = ImageDebugType.CodeView; if (isEmbeddedPortablePdb) { Debug.Assert(embeddedMemoryStream != null); var embedEntry = debugDirectory.Add(CreateEmbeddedPortablePdbBlob(embeddedMemoryStream)); embedEntry.DebugDirectory.TimeDateStamp = 0; embedEntry.DebugDirectory.MajorVersion = PortablePdbConstants.FormatVersion; embedEntry.DebugDirectory.MinorVersion = PortablePdbConstants.EmbeddedVersion; embedEntry.DebugDirectory.Type = ImageDebugType.EmbeddedPortablePdb; } } finally { if (ownsStream && pdbStream != null) pdbStream.Dispose(); } } static byte[] CreateEmbeddedPortablePdbBlob(MemoryStream portablePdbStream) { var compressedData = Compress(portablePdbStream); var data = new byte[4 + 4 + compressedData.Length]; var stream = new MemoryStream(data); var writer = new BinaryWriter(stream); writer.Write(0x4244504D);//"MPDB" writer.Write((uint)portablePdbStream.Length); writer.Write(compressedData); Debug.Assert(stream.Position == data.Length); return data; } static byte[] Compress(MemoryStream sourceStream) { sourceStream.Position = 0; var destStream = new MemoryStream(); using (var deflate = new DeflateStream(destStream, CompressionMode.Compress)) { var source = sourceStream.ToArray(); deflate.Write(source, 0, source.Length); } return destStream.ToArray(); } static byte[] GetCodeViewData(Guid guid, uint age, string filename) { var stream = new MemoryStream(); var writer = new BinaryWriter(stream); writer.Write(0x53445352); writer.Write(guid.ToByteArray()); writer.Write(age); writer.Write(Encoding.UTF8.GetBytes(filename)); writer.Write((byte)0); return stream.ToArray(); } Stream GetStandalonePortablePdbStream(out bool ownsStream) { if (TheOptions.PdbStream != null) { ownsStream = false; return TheOptions.PdbStream; } if (!string.IsNullOrEmpty(TheOptions.PdbFileName)) createdPdbFileName = TheOptions.PdbFileName; else createdPdbFileName = GetDefaultPdbFileName(); if (createdPdbFileName == null) { ownsStream = false; return null; } ownsStream = true; return File.Create(createdPdbFileName); } /// void IMetaDataListener.OnMetaDataEvent(MetaData metaData, MetaDataEvent evt) { switch (evt) { case MetaDataEvent.BeginCreateTables: Listener.OnWriterEvent(this, ModuleWriterEvent.MDBeginCreateTables); break; case MetaDataEvent.AllocateTypeDefRids: Listener.OnWriterEvent(this, ModuleWriterEvent.MDAllocateTypeDefRids); break; case MetaDataEvent.AllocateMemberDefRids: Listener.OnWriterEvent(this, ModuleWriterEvent.MDAllocateMemberDefRids); break; case MetaDataEvent.AllocateMemberDefRids0: Listener.OnWriterEvent(this, ModuleWriterEvent.MDAllocateMemberDefRids0); break; case MetaDataEvent.AllocateMemberDefRids1: Listener.OnWriterEvent(this, ModuleWriterEvent.MDAllocateMemberDefRids1); break; case MetaDataEvent.AllocateMemberDefRids2: Listener.OnWriterEvent(this, ModuleWriterEvent.MDAllocateMemberDefRids2); break; case MetaDataEvent.AllocateMemberDefRids3: Listener.OnWriterEvent(this, ModuleWriterEvent.MDAllocateMemberDefRids3); break; case MetaDataEvent.AllocateMemberDefRids4: Listener.OnWriterEvent(this, ModuleWriterEvent.MDAllocateMemberDefRids4); break; case MetaDataEvent.MemberDefRidsAllocated: Listener.OnWriterEvent(this, ModuleWriterEvent.MDMemberDefRidsAllocated); break; case MetaDataEvent.InitializeTypeDefsAndMemberDefs0: Listener.OnWriterEvent(this, ModuleWriterEvent.MDInitializeTypeDefsAndMemberDefs0); break; case MetaDataEvent.InitializeTypeDefsAndMemberDefs1: Listener.OnWriterEvent(this, ModuleWriterEvent.MDInitializeTypeDefsAndMemberDefs1); break; case MetaDataEvent.InitializeTypeDefsAndMemberDefs2: Listener.OnWriterEvent(this, ModuleWriterEvent.MDInitializeTypeDefsAndMemberDefs2); break; case MetaDataEvent.InitializeTypeDefsAndMemberDefs3: Listener.OnWriterEvent(this, ModuleWriterEvent.MDInitializeTypeDefsAndMemberDefs3); break; case MetaDataEvent.InitializeTypeDefsAndMemberDefs4: Listener.OnWriterEvent(this, ModuleWriterEvent.MDInitializeTypeDefsAndMemberDefs4); break; case MetaDataEvent.MemberDefsInitialized: Listener.OnWriterEvent(this, ModuleWriterEvent.MDMemberDefsInitialized); break; case MetaDataEvent.BeforeSortTables: Listener.OnWriterEvent(this, ModuleWriterEvent.MDBeforeSortTables); break; case MetaDataEvent.MostTablesSorted: Listener.OnWriterEvent(this, ModuleWriterEvent.MDMostTablesSorted); break; case MetaDataEvent.WriteTypeDefAndMemberDefCustomAttributes0: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteTypeDefAndMemberDefCustomAttributes0); break; case MetaDataEvent.WriteTypeDefAndMemberDefCustomAttributes1: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteTypeDefAndMemberDefCustomAttributes1); break; case MetaDataEvent.WriteTypeDefAndMemberDefCustomAttributes2: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteTypeDefAndMemberDefCustomAttributes2); break; case MetaDataEvent.WriteTypeDefAndMemberDefCustomAttributes3: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteTypeDefAndMemberDefCustomAttributes3); break; case MetaDataEvent.WriteTypeDefAndMemberDefCustomAttributes4: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteTypeDefAndMemberDefCustomAttributes4); break; case MetaDataEvent.MemberDefCustomAttributesWritten: Listener.OnWriterEvent(this, ModuleWriterEvent.MDMemberDefCustomAttributesWritten); break; case MetaDataEvent.BeginAddResources: Listener.OnWriterEvent(this, ModuleWriterEvent.MDBeginAddResources); break; case MetaDataEvent.EndAddResources: Listener.OnWriterEvent(this, ModuleWriterEvent.MDEndAddResources); break; case MetaDataEvent.BeginWriteMethodBodies: Listener.OnWriterEvent(this, ModuleWriterEvent.MDBeginWriteMethodBodies); break; case MetaDataEvent.WriteMethodBodies0: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteMethodBodies0); break; case MetaDataEvent.WriteMethodBodies1: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteMethodBodies1); break; case MetaDataEvent.WriteMethodBodies2: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteMethodBodies2); break; case MetaDataEvent.WriteMethodBodies3: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteMethodBodies3); break; case MetaDataEvent.WriteMethodBodies4: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteMethodBodies4); break; case MetaDataEvent.WriteMethodBodies5: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteMethodBodies5); break; case MetaDataEvent.WriteMethodBodies6: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteMethodBodies6); break; case MetaDataEvent.WriteMethodBodies7: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteMethodBodies7); break; case MetaDataEvent.WriteMethodBodies8: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteMethodBodies8); break; case MetaDataEvent.WriteMethodBodies9: Listener.OnWriterEvent(this, ModuleWriterEvent.MDWriteMethodBodies9); break; case MetaDataEvent.EndWriteMethodBodies: Listener.OnWriterEvent(this, ModuleWriterEvent.MDEndWriteMethodBodies); break; case MetaDataEvent.OnAllTablesSorted: Listener.OnWriterEvent(this, ModuleWriterEvent.MDOnAllTablesSorted); break; case MetaDataEvent.EndCreateTables: Listener.OnWriterEvent(this, ModuleWriterEvent.MDEndCreateTables); break; default: break; } } ILogger GetLogger() { return TheOptions.Logger ?? DummyLogger.ThrowModuleWriterExceptionOnErrorInstance; } /// void ILogger.Log(object sender, LoggerEvent loggerEvent, string format, params object[] args) { GetLogger().Log(this, loggerEvent, format, args); } /// bool ILogger.IgnoresEvent(LoggerEvent loggerEvent) { return GetLogger().IgnoresEvent(loggerEvent); } /// /// Logs an error message /// /// Format /// Format args protected void Error(string format, params object[] args) { GetLogger().Log(this, LoggerEvent.Error, format, args); } /// /// Logs a warning message /// /// Format /// Format args protected void Warning(string format, params object[] args) { GetLogger().Log(this, LoggerEvent.Warning, format, args); } } } dnlib-2.1_VS2010/src/DotNet/Writer/ModuleWriterException.cs000066400000000000000000000020731325033663500234570ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Runtime.Serialization; namespace dnlib.DotNet.Writer { /// /// Thrown when the module writer encounters an unrecoverable error /// [Serializable] public class ModuleWriterException : Exception { /// /// Default constructor /// public ModuleWriterException() { } /// /// Constructor /// /// Error message public ModuleWriterException(string message) : base(message) { } /// /// Constructor /// /// Error message /// Other exception public ModuleWriterException(string message, Exception innerException) : base(message, innerException) { } /// /// Constructor /// /// /// protected ModuleWriterException(SerializationInfo info, StreamingContext context) : base(info, context) { } } } dnlib-2.1_VS2010/src/DotNet/Writer/NativeModuleWriter.cs000066400000000000000000000607021325033663500227520ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.IO; using dnlib.PE; using dnlib.W32Resources; using dnlib.DotNet.MD; namespace dnlib.DotNet.Writer { /// /// options /// public sealed class NativeModuleWriterOptions : ModuleWriterOptionsBase { /// /// If true, any extra data after the PE data in the original file is also saved /// at the end of the new file. Enable this option if some protector has written data to /// the end of the file and uses it at runtime. /// public bool KeepExtraPEData { get; set; } /// /// If true, keep the original Win32 resources /// public bool KeepWin32Resources { get; set; } /// /// Constructor /// /// Module public NativeModuleWriterOptions(ModuleDefMD module) : this(module, null) { } /// /// Constructor /// /// Module /// Module writer listener public NativeModuleWriterOptions(ModuleDefMD module, IModuleWriterListener listener) : base(module, listener) { // C++ .NET mixed mode assemblies sometimes/often call Module.ResolveMethod(), // so method metadata tokens must be preserved. MetaDataOptions.Flags |= MetaDataFlags.PreserveAllMethodRids; } } /// /// A module writer that supports saving mixed-mode modules (modules with native code). /// The original image will be re-used. See also /// public sealed class NativeModuleWriter : ModuleWriterBase { /// The original .NET module readonly ModuleDefMD module; /// All options NativeModuleWriterOptions options; /// /// Any extra data found at the end of the original file. This is null if there's /// no extra data or if is /// false. /// BinaryReaderChunk extraData; /// The original PE headers BinaryReaderChunk headerSection; /// The original PE sections and their data List origSections; /// Original PE image readonly IPEImage peImage; /// New sections we've added and their data List sections; /// New .text section where we put some stuff, eg. .NET metadata PESection textSection; /// The new COR20 header ByteArrayChunk imageCor20Header; /// /// New .rsrc section where we put the new Win32 resources. This is null if there /// are no Win32 resources or if /// is true /// PESection rsrcSection; /// /// Offset in of the PE checksum field. /// long checkSumOffset; /// /// Original PE section /// public sealed class OrigSection : IDisposable { /// PE section public ImageSectionHeader PESection; /// PE section data public BinaryReaderChunk Chunk; /// /// Constructor /// /// PE section public OrigSection(ImageSectionHeader peSection) { this.PESection = peSection; } /// public void Dispose() { if (Chunk != null) Chunk.Data.Dispose(); Chunk = null; PESection = null; } /// public override string ToString() { uint offs = Chunk.Data is IImageStream ? (uint)((IImageStream)Chunk.Data).FileOffset : 0; return string.Format("{0} FO:{1:X8} L:{2:X8}", PESection.DisplayName, offs, (uint)Chunk.Data.Length); } } /// /// Gets the module /// public ModuleDefMD ModuleDefMD { get { return module; } } /// public override ModuleDef Module { get { return module; } } /// public override ModuleWriterOptionsBase TheOptions { get { return Options; } } /// /// Gets/sets the writer options. This is never null /// public NativeModuleWriterOptions Options { get { return options ?? (options = new NativeModuleWriterOptions(module)); } set { options = value; } } /// /// Gets all s /// public override List Sections { get { return sections; } } /// /// Gets the original PE sections and their data /// public List OrigSections { get { return origSections; } } /// /// Gets the .text section /// public override PESection TextSection { get { return textSection; } } /// /// Gets the .rsrc section or null if there's none /// public override PESection RsrcSection { get { return rsrcSection; } } /// /// Constructor /// /// The module /// Options or null public NativeModuleWriter(ModuleDefMD module, NativeModuleWriterOptions options) { this.module = module; this.options = options; this.peImage = module.MetaData.PEImage; } /// protected override long WriteImpl() { try { return Write(); } finally { if (origSections != null) { foreach (var section in origSections) section.Dispose(); } if (headerSection != null) headerSection.Data.Dispose(); if (extraData != null) extraData.Data.Dispose(); } } long Write() { Initialize(); // It's not safe to create new Field RVAs so re-use them all. The user can override // this by setting field.RVA = 0 when creating a new field.InitialValue. metaData.KeepFieldRVA = true; metaData.CreateTables(); return WriteFile(); } void Initialize() { CreateSections(); Listener.OnWriterEvent(this, ModuleWriterEvent.PESectionsCreated); CreateChunks(); Listener.OnWriterEvent(this, ModuleWriterEvent.ChunksCreated); AddChunksToSections(); Listener.OnWriterEvent(this, ModuleWriterEvent.ChunksAddedToSections); } void CreateSections() { CreatePESections(); CreateRawSections(); CreateHeaderSection(); CreateExtraData(); } void CreateChunks() { CreateMetaDataChunks(module); CreateDebugDirectory(); imageCor20Header = new ByteArrayChunk(new byte[0x48]); CreateStrongNameSignature(); } void AddChunksToSections() { textSection.Add(imageCor20Header, DEFAULT_COR20HEADER_ALIGNMENT); textSection.Add(strongNameSignature, DEFAULT_STRONGNAMESIG_ALIGNMENT); textSection.Add(constants, DEFAULT_CONSTANTS_ALIGNMENT); textSection.Add(methodBodies, DEFAULT_METHODBODIES_ALIGNMENT); textSection.Add(netResources, DEFAULT_NETRESOURCES_ALIGNMENT); textSection.Add(metaData, DEFAULT_METADATA_ALIGNMENT); textSection.Add(debugDirectory, DebugDirectory.DEFAULT_DEBUGDIRECTORY_ALIGNMENT); if (rsrcSection != null) rsrcSection.Add(win32Resources, DEFAULT_WIN32_RESOURCES_ALIGNMENT); } /// protected override Win32Resources GetWin32Resources() { if (Options.KeepWin32Resources) return null; return Options.Win32Resources ?? module.Win32Resources; } void CreatePESections() { sections = new List(); sections.Add(textSection = new PESection(".text", 0x60000020)); if (GetWin32Resources() != null) sections.Add(rsrcSection = new PESection(".rsrc", 0x40000040)); } /// /// Gets the raw section data of the image. The sections are saved in /// . /// void CreateRawSections() { var fileAlignment = peImage.ImageNTHeaders.OptionalHeader.FileAlignment; origSections = new List(peImage.ImageSectionHeaders.Count); foreach (var peSection in peImage.ImageSectionHeaders) { var newSection = new OrigSection(peSection); origSections.Add(newSection); uint sectionSize = Utils.AlignUp(peSection.SizeOfRawData, fileAlignment); newSection.Chunk = new BinaryReaderChunk(peImage.CreateStream(peSection.VirtualAddress, sectionSize), peSection.VirtualSize); } } /// /// Creates the PE header "section" /// void CreateHeaderSection() { uint afterLastSectHeader = GetOffsetAfterLastSectionHeader() + (uint)sections.Count * 0x28; uint firstRawOffset = Math.Min(GetFirstRawDataFileOffset(), peImage.ImageNTHeaders.OptionalHeader.SectionAlignment); uint headerLen = afterLastSectHeader; if (firstRawOffset > headerLen) headerLen = firstRawOffset; headerLen = Utils.AlignUp(headerLen, peImage.ImageNTHeaders.OptionalHeader.FileAlignment); if (headerLen <= peImage.ImageNTHeaders.OptionalHeader.SectionAlignment) { headerSection = new BinaryReaderChunk(peImage.CreateStream(0, headerLen)); return; } //TODO: Support this too throw new ModuleWriterException("Could not create header"); } uint GetOffsetAfterLastSectionHeader() { var lastSect = peImage.ImageSectionHeaders[peImage.ImageSectionHeaders.Count - 1]; return (uint)lastSect.EndOffset; } uint GetFirstRawDataFileOffset() { uint len = uint.MaxValue; foreach (var section in peImage.ImageSectionHeaders) len = Math.Min(len, section.PointerToRawData); return len; } /// /// Saves any data that is appended to the original PE file /// void CreateExtraData() { if (!Options.KeepExtraPEData) return; var lastOffs = GetLastFileSectionOffset(); extraData = new BinaryReaderChunk(peImage.CreateStream((FileOffset)lastOffs)); if (extraData.Data.Length == 0) { extraData.Data.Dispose(); extraData = null; } } uint GetLastFileSectionOffset() { uint rva = 0; foreach (var sect in origSections) rva = Math.Max(rva, (uint)sect.PESection.VirtualAddress + sect.PESection.SizeOfRawData); return (uint)peImage.ToFileOffset((RVA)(rva - 1)) + 1; } long WriteFile() { uint entryPointToken; bool entryPointIsManagedOrNoEntryPoint = GetEntryPoint(out entryPointToken); Listener.OnWriterEvent(this, ModuleWriterEvent.BeginWritePdb); WritePdbFile(); Listener.OnWriterEvent(this, ModuleWriterEvent.EndWritePdb); Listener.OnWriterEvent(this, ModuleWriterEvent.BeginCalculateRvasAndFileOffsets); var chunks = new List(); chunks.Add(headerSection); foreach (var origSection in origSections) chunks.Add(origSection.Chunk); foreach (var section in sections) chunks.Add(section); if (extraData != null) chunks.Add(extraData); CalculateRvasAndFileOffsets(chunks, 0, 0, peImage.ImageNTHeaders.OptionalHeader.FileAlignment, peImage.ImageNTHeaders.OptionalHeader.SectionAlignment); foreach (var section in origSections) { if (section.Chunk.RVA != section.PESection.VirtualAddress) throw new ModuleWriterException("Invalid section RVA"); } Listener.OnWriterEvent(this, ModuleWriterEvent.EndCalculateRvasAndFileOffsets); Listener.OnWriterEvent(this, ModuleWriterEvent.BeginWriteChunks); var writer = new BinaryWriter(destStream); WriteChunks(writer, chunks, 0, peImage.ImageNTHeaders.OptionalHeader.FileAlignment); long imageLength = writer.BaseStream.Position - destStreamBaseOffset; UpdateHeaderFields(writer, entryPointIsManagedOrNoEntryPoint, entryPointToken); Listener.OnWriterEvent(this, ModuleWriterEvent.EndWriteChunks); Listener.OnWriterEvent(this, ModuleWriterEvent.BeginStrongNameSign); if (Options.StrongNameKey != null) StrongNameSign((long)strongNameSignature.FileOffset); Listener.OnWriterEvent(this, ModuleWriterEvent.EndStrongNameSign); Listener.OnWriterEvent(this, ModuleWriterEvent.BeginWritePEChecksum); if (Options.AddCheckSum) { destStream.Position = destStreamBaseOffset; uint newCheckSum = new BinaryReader(destStream).CalculatePECheckSum(imageLength, checkSumOffset); writer.BaseStream.Position = checkSumOffset; writer.Write(newCheckSum); } Listener.OnWriterEvent(this, ModuleWriterEvent.EndWritePEChecksum); return imageLength; } /// /// true if image is 64-bit /// bool Is64Bit() { return peImage.ImageNTHeaders.OptionalHeader is ImageOptionalHeader64; } Characteristics GetCharacteristics() { var ch = module.Characteristics; if (Is64Bit()) ch &= ~Characteristics._32BitMachine; else ch |= Characteristics._32BitMachine; if (Options.IsExeFile) ch &= ~Characteristics.Dll; else ch |= Characteristics.Dll; return ch; } /// /// Updates the PE header and COR20 header fields that need updating. All sections are /// also updated, and the new ones are added. /// void UpdateHeaderFields(BinaryWriter writer, bool entryPointIsManagedOrNoEntryPoint, uint entryPointToken) { long fileHeaderOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.FileHeader.StartOffset; long optionalHeaderOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.StartOffset; long sectionsOffset = destStreamBaseOffset + (long)peImage.ImageSectionHeaders[0].StartOffset; long dataDirOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.EndOffset - 16 * 8; long cor20Offset = destStreamBaseOffset + (long)imageCor20Header.FileOffset; uint fileAlignment = peImage.ImageNTHeaders.OptionalHeader.FileAlignment; uint sectionAlignment = peImage.ImageNTHeaders.OptionalHeader.SectionAlignment; // Update PE file header var peOptions = Options.PEHeadersOptions; writer.BaseStream.Position = fileHeaderOffset; writer.Write((ushort)(peOptions.Machine ?? module.Machine)); writer.Write((ushort)(origSections.Count + sections.Count)); WriteUInt32(writer, peOptions.TimeDateStamp); WriteUInt32(writer, peOptions.PointerToSymbolTable); WriteUInt32(writer, peOptions.NumberOfSymbols); writer.BaseStream.Position += 2; // sizeof(SizeOfOptionalHeader) writer.Write((ushort)(peOptions.Characteristics ?? GetCharacteristics())); // Update optional header var sectionSizes = new SectionSizes(fileAlignment, sectionAlignment, headerSection.GetVirtualSize(), GetSectionSizeInfos); writer.BaseStream.Position = optionalHeaderOffset; bool is32BitOptionalHeader = peImage.ImageNTHeaders.OptionalHeader is ImageOptionalHeader32; if (is32BitOptionalHeader) { writer.BaseStream.Position += 2; WriteByte(writer, peOptions.MajorLinkerVersion); WriteByte(writer, peOptions.MinorLinkerVersion); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.BaseStream.Position += 4; // EntryPoint writer.Write(sectionSizes.BaseOfCode); writer.Write(sectionSizes.BaseOfData); WriteUInt32(writer, peOptions.ImageBase); writer.BaseStream.Position += 8; // SectionAlignment, FileAlignment WriteUInt16(writer, peOptions.MajorOperatingSystemVersion); WriteUInt16(writer, peOptions.MinorOperatingSystemVersion); WriteUInt16(writer, peOptions.MajorImageVersion); WriteUInt16(writer, peOptions.MinorImageVersion); WriteUInt16(writer, peOptions.MajorSubsystemVersion); WriteUInt16(writer, peOptions.MinorSubsystemVersion); WriteUInt32(writer, peOptions.Win32VersionValue); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum WriteUInt16(writer, peOptions.Subsystem); WriteUInt16(writer, peOptions.DllCharacteristics); WriteUInt32(writer, peOptions.SizeOfStackReserve); WriteUInt32(writer, peOptions.SizeOfStackCommit); WriteUInt32(writer, peOptions.SizeOfHeapReserve); WriteUInt32(writer, peOptions.SizeOfHeapCommit); WriteUInt32(writer, peOptions.LoaderFlags); WriteUInt32(writer, peOptions.NumberOfRvaAndSizes); } else { writer.BaseStream.Position += 2; WriteByte(writer, peOptions.MajorLinkerVersion); WriteByte(writer, peOptions.MinorLinkerVersion); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.BaseStream.Position += 4; // EntryPoint writer.Write(sectionSizes.BaseOfCode); WriteUInt64(writer, peOptions.ImageBase); writer.BaseStream.Position += 8; // SectionAlignment, FileAlignment WriteUInt16(writer, peOptions.MajorOperatingSystemVersion); WriteUInt16(writer, peOptions.MinorOperatingSystemVersion); WriteUInt16(writer, peOptions.MajorImageVersion); WriteUInt16(writer, peOptions.MinorImageVersion); WriteUInt16(writer, peOptions.MajorSubsystemVersion); WriteUInt16(writer, peOptions.MinorSubsystemVersion); WriteUInt32(writer, peOptions.Win32VersionValue); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum WriteUInt16(writer, peOptions.Subsystem ?? GetSubsystem()); WriteUInt16(writer, peOptions.DllCharacteristics ?? module.DllCharacteristics); WriteUInt64(writer, peOptions.SizeOfStackReserve); WriteUInt64(writer, peOptions.SizeOfStackCommit); WriteUInt64(writer, peOptions.SizeOfHeapReserve); WriteUInt64(writer, peOptions.SizeOfHeapCommit); WriteUInt32(writer, peOptions.LoaderFlags); WriteUInt32(writer, peOptions.NumberOfRvaAndSizes); } // Update Win32 resources data directory, if we wrote a new one if (win32Resources != null) { writer.BaseStream.Position = dataDirOffset + 2 * 8; writer.WriteDataDirectory(win32Resources); } // Clear the security descriptor directory writer.BaseStream.Position = dataDirOffset + 4 * 8; writer.WriteDataDirectory(null); // Write a new debug directory writer.BaseStream.Position = dataDirOffset + 6 * 8; writer.WriteDataDirectory(debugDirectory); // Write a new Metadata data directory writer.BaseStream.Position = dataDirOffset + 14 * 8; writer.WriteDataDirectory(imageCor20Header); // Update old sections, and add new sections writer.BaseStream.Position = sectionsOffset; foreach (var section in origSections) { writer.BaseStream.Position += 0x14; writer.Write((uint)section.Chunk.FileOffset); // PointerToRawData writer.BaseStream.Position += 0x10; } foreach (var section in sections) section.WriteHeaderTo(writer, fileAlignment, sectionAlignment, (uint)section.RVA); // Write the .NET header writer.BaseStream.Position = cor20Offset; writer.Write(0x48); // cb WriteUInt16(writer, Options.Cor20HeaderOptions.MajorRuntimeVersion); WriteUInt16(writer, Options.Cor20HeaderOptions.MinorRuntimeVersion); writer.WriteDataDirectory(metaData); writer.Write((uint)GetComImageFlags(entryPointIsManagedOrNoEntryPoint)); writer.Write(entryPointToken); writer.WriteDataDirectory(netResources); writer.WriteDataDirectory(strongNameSignature); WriteDataDirectory(writer, module.MetaData.ImageCor20Header.CodeManagerTable); WriteDataDirectory(writer, module.MetaData.ImageCor20Header.VTableFixups); WriteDataDirectory(writer, module.MetaData.ImageCor20Header.ExportAddressTableJumps); WriteDataDirectory(writer, module.MetaData.ImageCor20Header.ManagedNativeHeader); UpdateVTableFixups(writer); } static void WriteDataDirectory(BinaryWriter writer, ImageDataDirectory dataDir) { writer.Write((uint)dataDir.VirtualAddress); writer.Write(dataDir.Size); } static void WriteByte(BinaryWriter writer, byte? value) { if (value == null) writer.BaseStream.Position++; else writer.Write(value.Value); } static void WriteUInt16(BinaryWriter writer, ushort? value) { if (value == null) writer.BaseStream.Position += 2; else writer.Write(value.Value); } static void WriteUInt16(BinaryWriter writer, Subsystem? value) { if (value == null) writer.BaseStream.Position += 2; else writer.Write((ushort)value.Value); } static void WriteUInt16(BinaryWriter writer, DllCharacteristics? value) { if (value == null) writer.BaseStream.Position += 2; else writer.Write((ushort)value.Value); } static void WriteUInt32(BinaryWriter writer, uint? value) { if (value == null) writer.BaseStream.Position += 4; else writer.Write(value.Value); } static void WriteUInt32(BinaryWriter writer, ulong? value) { if (value == null) writer.BaseStream.Position += 4; else writer.Write((uint)value.Value); } static void WriteUInt64(BinaryWriter writer, ulong? value) { if (value == null) writer.BaseStream.Position += 8; else writer.Write(value.Value); } ComImageFlags GetComImageFlags(bool isManagedEntryPoint) { var flags = Options.Cor20HeaderOptions.Flags ?? module.Cor20HeaderFlags; if (Options.Cor20HeaderOptions.EntryPoint != null) return flags; if (isManagedEntryPoint) return flags & ~ComImageFlags.NativeEntryPoint; return flags | ComImageFlags.NativeEntryPoint; } Subsystem GetSubsystem() { if (module.Kind == ModuleKind.Windows) return Subsystem.WindowsGui; return Subsystem.WindowsCui; } /// /// Converts to a file offset in the destination stream /// /// RVA long ToWriterOffset(RVA rva) { if (rva == 0) return 0; foreach (var sect in origSections) { var section = sect.PESection; if (section.VirtualAddress <= rva && rva < section.VirtualAddress + Math.Max(section.VirtualSize, section.SizeOfRawData)) return destStreamBaseOffset + (long)sect.Chunk.FileOffset + (rva - section.VirtualAddress); } return 0; } IEnumerable GetSectionSizeInfos() { foreach (var section in origSections) yield return new SectionSizeInfo(section.Chunk.GetVirtualSize(), section.PESection.Characteristics); foreach (var section in sections) yield return new SectionSizeInfo(section.GetVirtualSize(), section.Characteristics); } void UpdateVTableFixups(BinaryWriter writer) { var vtableFixups = module.VTableFixups; if (vtableFixups == null || vtableFixups.VTables.Count == 0) return; writer.BaseStream.Position = ToWriterOffset(vtableFixups.RVA); if (writer.BaseStream.Position == 0) { Error("Could not convert RVA to file offset"); return; } foreach (var vtable in vtableFixups) { if (vtable.Methods.Count > ushort.MaxValue) throw new ModuleWriterException("Too many methods in vtable"); writer.Write((uint)vtable.RVA); writer.Write((ushort)vtable.Methods.Count); writer.Write((ushort)vtable.Flags); long pos = writer.BaseStream.Position; writer.BaseStream.Position = ToWriterOffset(vtable.RVA); if (writer.BaseStream.Position == 0) { if (vtable.RVA != 0 || vtable.Methods.Count > 0) Error("Could not convert RVA to file offset"); } else { foreach (var method in vtable.Methods) { writer.Write(GetMethodToken(method)); if (vtable.Is64Bit) writer.Write(0); } } writer.BaseStream.Position = pos; } } uint GetMethodToken(IMethod method) { var md = method as MethodDef; if (md != null) return new MDToken(Table.Method, metaData.GetRid(md)).Raw; var mr = method as MemberRef; if (mr != null) return new MDToken(Table.MemberRef, metaData.GetRid(mr)).Raw; var ms = method as MethodSpec; if (ms != null) return new MDToken(Table.MethodSpec, metaData.GetRid(ms)).Raw; if (method == null) return 0; Error("Invalid VTable method type: {0}", method.GetType()); return 0; } /// /// Gets the entry point /// /// Updated with entry point (either a token or RVA of native method) /// true if it's a managed entry point or there's no entry point, /// false if it's a native entry point bool GetEntryPoint(out uint ep) { var tok = Options.Cor20HeaderOptions.EntryPoint; if (tok != null) { ep = tok.Value; return ep == 0 || ((Options.Cor20HeaderOptions.Flags ?? 0) & ComImageFlags.NativeEntryPoint) == 0; } var epMethod = module.ManagedEntryPoint as MethodDef; if (epMethod != null) { ep = new MDToken(Table.Method, metaData.GetRid(epMethod)).Raw; return true; } var file = module.ManagedEntryPoint as FileDef; if (file != null) { ep = new MDToken(Table.File, metaData.GetRid(file)).Raw; return true; } ep = (uint)module.NativeEntryPoint; return ep == 0; } } } dnlib-2.1_VS2010/src/DotNet/Writer/NetResources.cs000066400000000000000000000046061325033663500216030ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// .NET resources /// public sealed class NetResources : IChunk { readonly List resources = new List(); readonly uint alignment; uint length; bool setOffsetCalled; FileOffset offset; RVA rva; /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Gets offset of next resource. This offset is relative to the start of /// the .NET resources and is always aligned. /// public uint NextOffset { get { return length; } } /// /// Constructor /// /// Alignment of all resources public NetResources(uint alignment) { this.alignment = alignment; } /// /// Adds a resource /// /// The resource data /// The resource data public ByteArrayChunk Add(IImageStream stream) { if (setOffsetCalled) throw new InvalidOperationException("SetOffset() has already been called"); var rawData = stream.ReadAllBytes(); length = Utils.AlignUp(length + 4 + (uint)rawData.Length, alignment); var data = new ByteArrayChunk(rawData); resources.Add(data); return data; } /// public void SetOffset(FileOffset offset, RVA rva) { setOffsetCalled = true; this.offset = offset; this.rva = rva; foreach (var resource in resources) { resource.SetOffset(offset + 4, rva + 4); uint len = 4 + resource.GetFileLength(); offset = (offset + len).AlignUp(alignment); rva = (rva + len).AlignUp(alignment); } } /// public uint GetFileLength() { return length; } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { RVA rva2 = rva; foreach (var resourceData in resources) { writer.Write(resourceData.GetFileLength()); resourceData.VerifyWriteTo(writer); rva2 += 4 + resourceData.GetFileLength(); int padding = (int)rva2.AlignUp(alignment) - (int)rva2; writer.WriteZeros(padding); rva2 += (uint)padding; } } } } dnlib-2.1_VS2010/src/DotNet/Writer/NormalMetaData.cs000066400000000000000000000247771325033663500220260ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using dnlib.DotNet.MD; namespace dnlib.DotNet.Writer { /// /// Does not preserve metadata tokens /// sealed class NormalMetaData : MetaData { readonly Rows typeRefInfos = new Rows(); readonly Rows typeDefInfos = new Rows(); readonly Rows fieldDefInfos = new Rows(); readonly Rows methodDefInfos = new Rows(); readonly Rows paramDefInfos = new Rows(); readonly Rows memberRefInfos = new Rows(); readonly Rows standAloneSigInfos = new Rows(); readonly Rows eventDefInfos = new Rows(); readonly Rows propertyDefInfos = new Rows(); readonly Rows typeSpecInfos = new Rows(); readonly Rows methodSpecInfos = new Rows(); protected override int NumberOfMethods { get { return methodDefInfos.Count; } } public NormalMetaData(ModuleDef module, UniqueChunkList constants, MethodBodyChunks methodBodies, NetResources netResources, MetaDataOptions options, DebugMetaDataKind debugKind, bool isStandaloneDebugMetadata) : base(module, constants, methodBodies, netResources, options, debugKind, isStandaloneDebugMetadata) { } /// protected override List GetAllTypeDefs() { // All nested types must be after their enclosing type. This is exactly // what module.GetTypes() does. return new List(module.GetTypes()); } /// protected override void AllocateTypeDefRids() { foreach (var type in allTypeDefs) { if (type == null) continue; uint rid = tablesHeap.TypeDefTable.Create(new RawTypeDefRow()); typeDefInfos.Add(type, rid); } } /// protected override void AllocateMemberDefRids() { int numTypes = allTypeDefs.Count; int typeNum = 0; int notifyNum = 0; const int numNotifyEvents = 5; // AllocateMemberDefRids0 - AllocateMemberDefRids4 int notifyAfter = numTypes / numNotifyEvents; uint fieldListRid = 1, methodListRid = 1; uint eventListRid = 1, propertyListRid = 1; uint paramListRid = 1; foreach (var type in allTypeDefs) { if (typeNum++ == notifyAfter && notifyNum < numNotifyEvents) { Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids0 + notifyNum++); notifyAfter += numTypes / numNotifyEvents; } if (type == null) continue; uint typeRid = GetRid(type); var typeRow = tablesHeap.TypeDefTable[typeRid]; typeRow.FieldList = fieldListRid; typeRow.MethodList = methodListRid; foreach (var field in type.Fields) { if (field == null) continue; uint rid = fieldListRid++; if (rid != tablesHeap.FieldTable.Create(new RawFieldRow())) throw new ModuleWriterException("Invalid field rid"); fieldDefInfos.Add(field, rid); } foreach (var method in type.Methods) { if (method == null) continue; uint rid = methodListRid++; var row = new RawMethodRow(0, 0, 0, 0, 0, paramListRid); if (rid != tablesHeap.MethodTable.Create(row)) throw new ModuleWriterException("Invalid method rid"); methodDefInfos.Add(method, rid); foreach (var pd in Sort(method.ParamDefs)) { if (pd == null) continue; uint pdRid = paramListRid++; if (pdRid != tablesHeap.ParamTable.Create(new RawParamRow())) throw new ModuleWriterException("Invalid param rid"); paramDefInfos.Add(pd, pdRid); } } if (!IsEmpty(type.Events)) { uint eventMapRid = tablesHeap.EventMapTable.Create(new RawEventMapRow(typeRid, eventListRid)); eventMapInfos.Add(type, eventMapRid); foreach (var evt in type.Events) { if (evt == null) continue; uint rid = eventListRid++; if (rid != tablesHeap.EventTable.Create(new RawEventRow())) throw new ModuleWriterException("Invalid event rid"); eventDefInfos.Add(evt, rid); } } if (!IsEmpty(type.Properties)) { uint propertyMapRid = tablesHeap.PropertyMapTable.Create(new RawPropertyMapRow(typeRid, propertyListRid)); propertyMapInfos.Add(type, propertyMapRid); foreach (var prop in type.Properties) { if (prop == null) continue; uint rid = propertyListRid++; if (rid != tablesHeap.PropertyTable.Create(new RawPropertyRow())) throw new ModuleWriterException("Invalid property rid"); propertyDefInfos.Add(prop, rid); } } } while (notifyNum < numNotifyEvents) Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids0 + notifyNum++); } /// public override uint GetRid(TypeRef tr) { uint rid; typeRefInfos.TryGetRid(tr, out rid); return rid; } /// public override uint GetRid(TypeDef td) { uint rid; if (typeDefInfos.TryGetRid(td, out rid)) return rid; if (td == null) Error("TypeDef is null"); else Error("TypeDef {0} ({1:X8}) is not defined in this module ({2}). A type was removed that is still referenced by this module.", td, td.MDToken.Raw, module); return 0; } /// public override uint GetRid(FieldDef fd) { uint rid; if (fieldDefInfos.TryGetRid(fd, out rid)) return rid; if (fd == null) Error("Field is null"); else Error("Field {0} ({1:X8}) is not defined in this module ({2}). A field was removed that is still referenced by this module.", fd, fd.MDToken.Raw, module); return 0; } /// public override uint GetRid(MethodDef md) { uint rid; if (methodDefInfos.TryGetRid(md, out rid)) return rid; if (md == null) Error("Method is null"); else Error("Method {0} ({1:X8}) is not defined in this module ({2}). A method was removed that is still referenced by this module.", md, md.MDToken.Raw, module); return 0; } /// public override uint GetRid(ParamDef pd) { uint rid; if (paramDefInfos.TryGetRid(pd, out rid)) return rid; if (pd == null) Error("Param is null"); else Error("Param {0} ({1:X8}) is not defined in this module ({2}). A parameter was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); return 0; } /// public override uint GetRid(MemberRef mr) { uint rid; memberRefInfos.TryGetRid(mr, out rid); return rid; } /// public override uint GetRid(StandAloneSig sas) { uint rid; standAloneSigInfos.TryGetRid(sas, out rid); return rid; } /// public override uint GetRid(EventDef ed) { uint rid; if (eventDefInfos.TryGetRid(ed, out rid)) return rid; if (ed == null) Error("Event is null"); else Error("Event {0} ({1:X8}) is not defined in this module ({2}). An event was removed that is still referenced by this module.", ed, ed.MDToken.Raw, module); return 0; } /// public override uint GetRid(PropertyDef pd) { uint rid; if (propertyDefInfos.TryGetRid(pd, out rid)) return rid; if (pd == null) Error("Property is null"); else Error("Property {0} ({1:X8}) is not defined in this module ({2}). A property was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); return 0; } /// public override uint GetRid(TypeSpec ts) { uint rid; typeSpecInfos.TryGetRid(ts, out rid); return rid; } /// public override uint GetRid(MethodSpec ms) { uint rid; methodSpecInfos.TryGetRid(ms, out rid); return rid; } /// protected override uint AddTypeRef(TypeRef tr) { if (tr == null) { Error("TypeRef is null"); return 0; } uint rid; if (typeRefInfos.TryGetRid(tr, out rid)) { if (rid == 0) Error("TypeRef {0:X8} has an infinite ResolutionScope loop", tr.MDToken.Raw); return rid; } typeRefInfos.Add(tr, 0); // Prevent inf recursion var row = new RawTypeRefRow(AddResolutionScope(tr.ResolutionScope), stringsHeap.Add(tr.Name), stringsHeap.Add(tr.Namespace)); rid = tablesHeap.TypeRefTable.Add(row); typeRefInfos.SetRid(tr, rid); AddCustomAttributes(Table.TypeRef, rid, tr); AddCustomDebugInformationList(Table.TypeRef, rid, tr); return rid; } /// protected override uint AddTypeSpec(TypeSpec ts) { if (ts == null) { Error("TypeSpec is null"); return 0; } uint rid; if (typeSpecInfos.TryGetRid(ts, out rid)) { if (rid == 0) Error("TypeSpec {0:X8} has an infinite TypeSig loop", ts.MDToken.Raw); return rid; } typeSpecInfos.Add(ts, 0); // Prevent inf recursion var row = new RawTypeSpecRow(GetSignature(ts.TypeSig, ts.ExtraData)); rid = tablesHeap.TypeSpecTable.Add(row); typeSpecInfos.SetRid(ts, rid); AddCustomAttributes(Table.TypeSpec, rid, ts); AddCustomDebugInformationList(Table.TypeSpec, rid, ts); return rid; } /// protected override uint AddMemberRef(MemberRef mr) { if (mr == null) { Error("MemberRef is null"); return 0; } uint rid; if (memberRefInfos.TryGetRid(mr, out rid)) return rid; var row = new RawMemberRefRow(AddMemberRefParent(mr.Class), stringsHeap.Add(mr.Name), GetSignature(mr.Signature)); rid = tablesHeap.MemberRefTable.Add(row); memberRefInfos.Add(mr, rid); AddCustomAttributes(Table.MemberRef, rid, mr); AddCustomDebugInformationList(Table.MemberRef, rid, mr); return rid; } /// protected override uint AddStandAloneSig(StandAloneSig sas) { if (sas == null) { Error("StandAloneSig is null"); return 0; } uint rid; if (standAloneSigInfos.TryGetRid(sas, out rid)) return rid; var row = new RawStandAloneSigRow(GetSignature(sas.Signature)); rid = tablesHeap.StandAloneSigTable.Add(row); standAloneSigInfos.Add(sas, rid); AddCustomAttributes(Table.StandAloneSig, rid, sas); AddCustomDebugInformationList(Table.StandAloneSig, rid, sas); return rid; } /// protected override uint AddMethodSpec(MethodSpec ms) { if (ms == null) { Error("MethodSpec is null"); return 0; } uint rid; if (methodSpecInfos.TryGetRid(ms, out rid)) return rid; var row = new RawMethodSpecRow(AddMethodDefOrRef(ms.Method), GetSignature(ms.Instantiation)); rid = tablesHeap.MethodSpecTable.Add(row); methodSpecInfos.Add(ms, rid); AddCustomAttributes(Table.MethodSpec, rid, ms); AddCustomDebugInformationList(Table.MethodSpec, rid, ms); return rid; } } } dnlib-2.1_VS2010/src/DotNet/Writer/PEHeaders.cs000066400000000000000000000367671325033663500207770ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// options /// public sealed class PEHeadersOptions { /// /// Default DLL characteristics /// public const DllCharacteristics DefaultDllCharacteristics = dnlib.PE.DllCharacteristics.TerminalServerAware | dnlib.PE.DllCharacteristics.NoSeh | dnlib.PE.DllCharacteristics.NxCompat | dnlib.PE.DllCharacteristics.DynamicBase; /// /// Default subsystem value /// public const Subsystem DEFAULT_SUBSYSTEM = dnlib.PE.Subsystem.WindowsGui; /// /// Default major linker version /// public const byte DEFAULT_MAJOR_LINKER_VERSION = 11; /// /// Default minor linker version /// public const byte DEFAULT_MINOR_LINKER_VERSION = 0; /// /// IMAGE_FILE_HEADER.Machine value /// public Machine? Machine; /// /// IMAGE_FILE_HEADER.TimeDateStamp value /// public uint? TimeDateStamp; /// /// IMAGE_FILE_HEADER.PointerToSymbolTable value /// public uint? PointerToSymbolTable; /// /// IMAGE_FILE_HEADER.NumberOfSymbols value /// public uint? NumberOfSymbols; /// /// IMAGE_FILE_HEADER.Characteristics value. bit /// is ignored and set/cleared depending on whether it's a EXE or a DLL file. /// public Characteristics? Characteristics; /// /// IMAGE_OPTIONAL_HEADER.MajorLinkerVersion value /// public byte? MajorLinkerVersion; /// /// IMAGE_OPTIONAL_HEADER.MinorLinkerVersion value /// public byte? MinorLinkerVersion; /// /// IMAGE_OPTIONAL_HEADER.ImageBase value /// public ulong? ImageBase; /// /// IMAGE_OPTIONAL_HEADER.SectionAlignment value /// public uint? SectionAlignment; /// /// IMAGE_OPTIONAL_HEADER.FileAlignment value /// public uint? FileAlignment; /// /// IMAGE_OPTIONAL_HEADER.MajorOperatingSystemVersion value /// public ushort? MajorOperatingSystemVersion; /// /// IMAGE_OPTIONAL_HEADER.MinorOperatingSystemVersion value /// public ushort? MinorOperatingSystemVersion; /// /// IMAGE_OPTIONAL_HEADER.MajorImageVersion value /// public ushort? MajorImageVersion; /// /// IMAGE_OPTIONAL_HEADER.MinorImageVersion value /// public ushort? MinorImageVersion; /// /// IMAGE_OPTIONAL_HEADER.MajorSubsystemVersion value /// public ushort? MajorSubsystemVersion; /// /// IMAGE_OPTIONAL_HEADER.MinorSubsystemVersion value /// public ushort? MinorSubsystemVersion; /// /// IMAGE_OPTIONAL_HEADER.Win32VersionValue value /// public uint? Win32VersionValue; /// /// IMAGE_OPTIONAL_HEADER.Subsystem value /// public Subsystem? Subsystem; /// /// IMAGE_OPTIONAL_HEADER.DllCharacteristics value /// public DllCharacteristics? DllCharacteristics; /// /// IMAGE_OPTIONAL_HEADER.SizeOfStackReserve value /// public ulong? SizeOfStackReserve; /// /// IMAGE_OPTIONAL_HEADER.SizeOfStackCommit value /// public ulong? SizeOfStackCommit; /// /// IMAGE_OPTIONAL_HEADER.SizeOfHeapReserve value /// public ulong? SizeOfHeapReserve; /// /// IMAGE_OPTIONAL_HEADER.SizeOfHeapCommit value /// public ulong? SizeOfHeapCommit; /// /// IMAGE_OPTIONAL_HEADER.LoaderFlags value /// public uint? LoaderFlags; /// /// IMAGE_OPTIONAL_HEADER.NumberOfRvaAndSizes value /// public uint? NumberOfRvaAndSizes; /// /// Creates a new time date stamp using current time /// /// A new time date stamp public static uint CreateNewTimeDateStamp() { return (uint)(DateTime.UtcNow - Epoch).TotalSeconds; } static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); } /// /// DOS and PE headers /// public sealed class PEHeaders : IChunk { IList sections; readonly PEHeadersOptions options; FileOffset offset; RVA rva; uint length; readonly uint sectionAlignment; readonly uint fileAlignment; ulong imageBase; long startOffset; long checkSumOffset; bool isExeFile; // Copied from Partition II.25.2.1 static readonly byte[] dosHeader = new byte[0x80] { 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; /// /// Gets/sets the native entry point /// public StartupStub StartupStub { get; set; } /// /// Gets/sets the COR20 header /// public ImageCor20Header ImageCor20Header { get; set; } /// /// Gets/sets the IAT /// public ImportAddressTable ImportAddressTable { get; set; } /// /// Gets/sets the /// public ImportDirectory ImportDirectory { get; set; } /// /// Gets/sets the Win32 resources /// public Win32ResourcesChunk Win32Resources { get; set; } /// /// Gets/sets the relocation directory /// public RelocDirectory RelocDirectory { get; set; } /// /// Gets/sets the debug directory /// public DebugDirectory DebugDirectory { get; set; } internal IChunk ExportDirectory { get; set; } /// /// Gets the image base /// public ulong ImageBase { get { return imageBase; } } /// /// Gets/sets a value indicating whether this is a EXE or a DLL file /// public bool IsExeFile { get { return isExeFile; } set { isExeFile = value; } } /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Gets the section alignment /// public uint SectionAlignment { get { return sectionAlignment; } } /// /// Gets the file alignment /// public uint FileAlignment { get { return fileAlignment; } } /// /// Gets/sets the s /// public IList PESections { get { return sections; } set { sections = value; } } /// /// Default constructor /// public PEHeaders() : this(new PEHeadersOptions()) { } /// /// Constructor /// /// Options public PEHeaders(PEHeadersOptions options) { this.options = options ?? new PEHeadersOptions(); this.sectionAlignment = this.options.SectionAlignment ?? 0x2000; this.fileAlignment = this.options.FileAlignment ?? 0x200; } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; length = (uint)dosHeader.Length; length += 4 + 0x14; length += Use32BitOptionalHeader() ? 0xE0U : 0xF0; length += (uint)sections.Count * 0x28; if (Use32BitOptionalHeader()) imageBase = options.ImageBase ?? 0x00400000; else imageBase = options.ImageBase ?? 0x0000000140000000; } int SectionsCount { get { int count = 0; foreach (var section in sections) { if (section.GetVirtualSize() != 0) count++; } return count; } } /// public uint GetFileLength() { return length; } /// public uint GetVirtualSize() { return GetFileLength(); } IEnumerable GetSectionSizeInfos() { foreach (var section in sections) { uint virtSize = section.GetVirtualSize(); if (virtSize != 0) yield return new SectionSizeInfo(virtSize, section.Characteristics); } } /// public void WriteTo(BinaryWriter writer) { startOffset = writer.BaseStream.Position; // DOS header writer.Write(dosHeader); // PE magic writer.Write(0x00004550); // Image file header writer.Write((ushort)GetMachine()); writer.Write((ushort)SectionsCount); Debug.Assert(SectionsCount == sections.Count, "One or more sections are empty! The PE file could be bigger than it should be. Empty sections should be removed."); writer.Write(options.TimeDateStamp ?? PEHeadersOptions.CreateNewTimeDateStamp()); writer.Write(options.PointerToSymbolTable ?? 0); writer.Write(options.NumberOfSymbols ?? 0); writer.Write((ushort)(Use32BitOptionalHeader() ? 0xE0U : 0xF0)); writer.Write((ushort)GetCharacteristics()); var sectionSizes = new SectionSizes(fileAlignment, sectionAlignment, length, () => GetSectionSizeInfos()); // Image optional header uint ep = StartupStub == null ? 0 : (uint)StartupStub.EntryPointRVA; if (Use32BitOptionalHeader()) { writer.Write((ushort)0x010B); writer.Write(options.MajorLinkerVersion ?? PEHeadersOptions.DEFAULT_MAJOR_LINKER_VERSION); writer.Write(options.MinorLinkerVersion ?? PEHeadersOptions.DEFAULT_MINOR_LINKER_VERSION); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.Write(ep); writer.Write(sectionSizes.BaseOfCode); writer.Write(sectionSizes.BaseOfData); writer.Write((uint)imageBase); writer.Write(sectionAlignment); writer.Write(fileAlignment); writer.Write(options.MajorOperatingSystemVersion ?? 4); writer.Write(options.MinorOperatingSystemVersion ?? 0); writer.Write(options.MajorImageVersion ?? 0); writer.Write(options.MinorImageVersion ?? 0); writer.Write(options.MajorSubsystemVersion ?? 4); writer.Write(options.MinorSubsystemVersion ?? 0); writer.Write(options.Win32VersionValue ?? 0); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum writer.Write((ushort)(options.Subsystem ?? PEHeadersOptions.DEFAULT_SUBSYSTEM)); writer.Write((ushort)(options.DllCharacteristics ?? PEHeadersOptions.DefaultDllCharacteristics)); writer.Write((uint)(options.SizeOfStackReserve ?? 0x00100000)); writer.Write((uint)(options.SizeOfStackCommit ?? 0x00001000)); writer.Write((uint)(options.SizeOfHeapReserve ?? 0x00100000)); writer.Write((uint)(options.SizeOfHeapCommit ?? 0x00001000)); writer.Write(options.LoaderFlags ?? 0x00000000); writer.Write(options.NumberOfRvaAndSizes ?? 0x00000010); } else { writer.Write((ushort)0x020B); writer.Write(options.MajorLinkerVersion ?? PEHeadersOptions.DEFAULT_MAJOR_LINKER_VERSION); writer.Write(options.MinorLinkerVersion ?? PEHeadersOptions.DEFAULT_MINOR_LINKER_VERSION); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.Write(ep); writer.Write(sectionSizes.BaseOfCode); writer.Write(imageBase); writer.Write(sectionAlignment); writer.Write(fileAlignment); writer.Write(options.MajorOperatingSystemVersion ?? 4); writer.Write(options.MinorOperatingSystemVersion ?? 0); writer.Write(options.MajorImageVersion ?? 0); writer.Write(options.MinorImageVersion ?? 0); writer.Write(options.MajorSubsystemVersion ?? 4); writer.Write(options.MinorSubsystemVersion ?? 0); writer.Write(options.Win32VersionValue ?? 0); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum writer.Write((ushort)(options.Subsystem ?? PEHeadersOptions.DEFAULT_SUBSYSTEM)); writer.Write((ushort)(options.DllCharacteristics ?? PEHeadersOptions.DefaultDllCharacteristics)); writer.Write(options.SizeOfStackReserve ?? 0x0000000000400000); writer.Write(options.SizeOfStackCommit ?? 0x0000000000004000); writer.Write(options.SizeOfHeapReserve ?? 0x0000000000100000); writer.Write(options.SizeOfHeapCommit ?? 0x0000000000002000); writer.Write(options.LoaderFlags ?? 0x00000000); writer.Write(options.NumberOfRvaAndSizes ?? 0x00000010); } writer.WriteDataDirectory(ExportDirectory); writer.WriteDataDirectory(ImportDirectory); writer.WriteDataDirectory(Win32Resources); writer.WriteDataDirectory(null); // Exception table writer.WriteDataDirectory(null); // Certificate table writer.WriteDataDirectory(RelocDirectory); writer.WriteDataDirectory(DebugDirectory); writer.WriteDataDirectory(null); // Architecture-specific data writer.WriteDataDirectory(null); // Global pointer register RVA writer.WriteDataDirectory(null); // Thread local storage writer.WriteDataDirectory(null); // Load configuration table writer.WriteDataDirectory(null); // Bound import table writer.WriteDataDirectory(ImportAddressTable); writer.WriteDataDirectory(null); // Delay import descriptor writer.WriteDataDirectory(ImageCor20Header); writer.WriteDataDirectory(null); // Reserved // Sections uint rva = Utils.AlignUp(sectionSizes.SizeOfHeaders, sectionAlignment); int emptySections = 0; foreach (var section in sections) { if (section.GetVirtualSize() != 0) rva += section.WriteHeaderTo(writer, fileAlignment, sectionAlignment, rva); else emptySections++; } if (emptySections != 0) writer.BaseStream.Position += emptySections * 0x28; } /// /// Calculates the PE checksum and writes it to the checksum field /// /// Writer /// Length of PE file public void WriteCheckSum(BinaryWriter writer, long length) { writer.BaseStream.Position = startOffset; uint checkSum = new BinaryReader(writer.BaseStream).CalculatePECheckSum(length, checkSumOffset); writer.BaseStream.Position = checkSumOffset; writer.Write(checkSum); } Machine GetMachine() { return options.Machine ?? Machine.I386; } bool Use32BitOptionalHeader() { var mach = GetMachine(); return mach != Machine.IA64 && mach != Machine.AMD64 && mach != Machine.ARM64; } Characteristics GetCharacteristics() { var chr = options.Characteristics ?? GetDefaultCharacteristics(); if (IsExeFile) chr &= ~Characteristics.Dll; else chr |= Characteristics.Dll; return chr; } Characteristics GetDefaultCharacteristics() { if (Use32BitOptionalHeader()) return Characteristics._32BitMachine | Characteristics.ExecutableImage; return Characteristics.ExecutableImage | Characteristics.LargeAddressAware; } } } dnlib-2.1_VS2010/src/DotNet/Writer/PESection.cs000066400000000000000000000051121325033663500210040ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using System.Text; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// A PE section /// public sealed class PESection : ChunkList { string name; uint characteristics; /// /// Gets the name /// public string Name { get { return name; } set { name = value; } } /// /// Gets the Characteristics /// public uint Characteristics { get { return characteristics; } set { characteristics = value; } } /// /// true if this is a code section /// public bool IsCode { get { return (characteristics & 0x20) != 0; } } /// /// true if this is an initialized data section /// public bool IsInitializedData { get { return (characteristics & 0x40) != 0; } } /// /// true if this is an uninitialized data section /// public bool IsUninitializedData { get { return (characteristics & 0x80) != 0; } } /// /// Constructor /// /// Section name /// Section characteristics public PESection(string name, uint characteristics) { this.name = name; this.characteristics = characteristics; } /// /// Writes the section header to at its current position. /// Returns aligned virtual size (aligned to ) /// /// Writer /// File alignment /// Section alignment /// Current public uint WriteHeaderTo(BinaryWriter writer, uint fileAlignment, uint sectionAlignment, uint rva) { uint vs = GetVirtualSize(); uint fileLen = GetFileLength(); uint alignedVs = Utils.AlignUp(vs, sectionAlignment); uint rawSize = Utils.AlignUp(fileLen, fileAlignment); uint dataOffset = (uint)FileOffset; writer.Write(Encoding.UTF8.GetBytes(Name + "\0\0\0\0\0\0\0\0"), 0, 8); writer.Write(vs); // VirtualSize writer.Write((uint)rva); // VirtualAddress writer.Write(rawSize); // SizeOfRawData writer.Write(dataOffset); // PointerToRawData writer.Write(0); // PointerToRelocations writer.Write(0); // PointerToLinenumbers writer.Write((ushort)0); // NumberOfRelocations writer.Write((ushort)0); // NumberOfLinenumbers writer.Write(Characteristics); return alignedVs; } } } dnlib-2.1_VS2010/src/DotNet/Writer/PdbHeap.cs000066400000000000000000000050261325033663500204620ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; namespace dnlib.DotNet.Writer { /// /// #Pdb heap /// public sealed class PdbHeap : HeapBase { /// public override string Name { get { return "#Pdb"; } } /// /// Gets the PDB ID. This is always 20 bytes in size. /// public byte[] PdbId { get { return pdbId; } } readonly byte[] pdbId; /// /// Gets/sets the entry point token /// public uint EntryPoint { get { return entryPoint; } set { entryPoint = value; } } uint entryPoint; /// /// Gets/sets the referenced type system tables /// public ulong ReferencedTypeSystemTables { get { if (!referencedTypeSystemTablesInitd) throw new InvalidOperationException("ReferencedTypeSystemTables hasn't been initialized yet"); return referencedTypeSystemTables; } set { if (isReadOnly) throw new InvalidOperationException("Size has already been calculated, can't write a new value"); referencedTypeSystemTables = value; referencedTypeSystemTablesInitd = true; typeSystemTablesCount = 0; ulong l = value; while (l != 0) { if (((int)l & 1) != 0) typeSystemTablesCount++; l >>= 1; } } } ulong referencedTypeSystemTables; bool referencedTypeSystemTablesInitd; int typeSystemTablesCount; /// /// Gets the type system table rows. This table has 64 elements. /// public uint[] TypeSystemTableRows { get { return typeSystemTableRows; } } readonly uint[] typeSystemTableRows; /// /// Constructor /// public PdbHeap() { pdbId = new byte[20]; typeSystemTableRows = new uint[64]; } /// public override uint GetRawLength() { if (!referencedTypeSystemTablesInitd) throw new InvalidOperationException("ReferencedTypeSystemTables hasn't been initialized yet"); return (uint)(pdbId.Length + 4 + 8 + 4 * typeSystemTablesCount); } /// protected override void WriteToImpl(BinaryWriter writer) { if (!referencedTypeSystemTablesInitd) throw new InvalidOperationException("ReferencedTypeSystemTables hasn't been initialized yet"); writer.Write(pdbId); writer.Write(entryPoint); writer.Write(referencedTypeSystemTables); ulong t = referencedTypeSystemTables; for (int i = 0; i < typeSystemTableRows.Length; i++, t >>= 1) { if (((int)t & 1) != 0) writer.Write(typeSystemTableRows[i]); } } } } dnlib-2.1_VS2010/src/DotNet/Writer/PortablePdbConstants.cs000066400000000000000000000014241325033663500232500ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.DotNet.Writer { static class PortablePdbConstants { // See System.Reflection.Metadata.PortablePdbVersions // Portable PDB version (v1.0) // Format version is stored in DebugDirectory.MajorVersion // SRM: DefaultFormatVersion, MinFormatVersion public const ushort FormatVersion = 0x0100; // Embedded Portable PDB Blob verison (v1.0) // Embedded version is stored in DebugDirectory.MinorVersion // SRM: MinEmbeddedVersion, DefaultEmbeddedVersion, MinUnsupportedEmbeddedVersion public const ushort EmbeddedVersion = 0x0100; // Stored in DebugDirectory.MinorVersion and indicates that it's a portable PDB file // and not a Windows PDB file public const ushort PortableCodeViewVersionMagic = 0x504D; } } dnlib-2.1_VS2010/src/DotNet/Writer/PreserveTokensMetaData.cs000066400000000000000000001202121325033663500235320ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; using dnlib.DotNet.MD; namespace dnlib.DotNet.Writer { /// /// Preserves metadata tokens /// sealed class PreserveTokensMetaData : MetaData { readonly ModuleDefMD mod; readonly Rows typeRefInfos = new Rows(); readonly Dictionary typeToRid = new Dictionary(); MemberDefDict fieldDefInfos; MemberDefDict methodDefInfos; MemberDefDict paramDefInfos; readonly Rows memberRefInfos = new Rows(); readonly Rows standAloneSigInfos = new Rows(); MemberDefDict eventDefInfos; MemberDefDict propertyDefInfos; readonly Rows typeSpecInfos = new Rows(); readonly Rows methodSpecInfos = new Rows(); readonly Dictionary callConvTokenToSignature = new Dictionary(); [DebuggerDisplay("{Rid} -> {NewRid} {Def}")] sealed class MemberDefInfo where T : IMDTokenProvider { public readonly T Def; /// /// Its real rid /// public uint Rid; /// /// Its logical rid or real rid. If the ptr table exists (eg. MethodPtr), then it's /// an index into it, else it's the real rid. /// public uint NewRid; public MemberDefInfo(T def, uint rid) { this.Def = def; this.Rid = rid; this.NewRid = rid; } } [DebuggerDisplay("Count = {Count}")] sealed class MemberDefDict where T : IMDTokenProvider { readonly Type defMDType; uint userRid = 0x01000000; uint newRid = 1; int numDefMDs; int numDefUsers; int tableSize; bool wasSorted; readonly bool preserveRids; readonly bool enableRidToInfo; readonly Dictionary> defToInfo = new Dictionary>(); Dictionary> ridToInfo; readonly List> defs = new List>(); List> sortedDefs; readonly Dictionary collectionPositions = new Dictionary(); /// /// Gets total number of defs in the list. It does not necessarily return /// the table size. Use for that. /// public int Count { get { return defs.Count; } } /// /// Gets the number of rows that need to be created in the table /// public int TableSize { get { return tableSize; } } /// /// Returns true if the ptr table (eg. MethodPtr) is needed /// public bool NeedPtrTable { get { return preserveRids && !wasSorted; } } public MemberDefDict(Type defMDType, bool preserveRids) : this(defMDType, preserveRids, false) { } public MemberDefDict(Type defMDType, bool preserveRids, bool enableRidToInfo) { this.defMDType = defMDType; this.preserveRids = preserveRids; this.enableRidToInfo = enableRidToInfo; } public uint Rid(T def) { return defToInfo[def].Rid; } public bool TryGetRid(T def, out uint rid) { MemberDefInfo info; if (def == null || !defToInfo.TryGetValue(def, out info)) { rid = 0; return false; } rid = info.Rid; return true; } /// /// Sorts the table /// /// Comparer public void Sort(Comparison> comparer) { if (!preserveRids) { // It's already sorted sortedDefs = defs; return; } sortedDefs = new List>(defs); sortedDefs.Sort(comparer); wasSorted = true; for (int i = 0; i < sortedDefs.Count; i++) { var def = sortedDefs[i]; uint newRid = (uint)i + 1; def.NewRid = newRid; if (def.Rid != newRid) wasSorted = false; } } public MemberDefInfo Get(int i) { return defs[i]; } public MemberDefInfo GetSorted(int i) { return sortedDefs[i]; } public MemberDefInfo GetByRid(uint rid) { MemberDefInfo info; ridToInfo.TryGetValue(rid, out info); return info; } /// /// Adds a def. must be called after adding the last def. /// /// The def /// Collection position public void Add(T def, int collPos) { uint rid; if (def.GetType() == defMDType) { numDefMDs++; rid = preserveRids ? def.Rid : newRid++; } else { numDefUsers++; rid = preserveRids ? userRid++ : newRid++; } var info = new MemberDefInfo(def, rid); defToInfo[def] = info; defs.Add(info); collectionPositions.Add(def, collPos); } /// /// Must be called after 'ing the last def /// public void SortDefs() { // It's already sorted if we don't preserve rids if (preserveRids) { // Sort all def MDs before user defs defs.Sort((a, b) => a.Rid.CompareTo(b.Rid)); // Fix user created defs' rids uint newRid = numDefMDs == 0 ? 1 : defs[numDefMDs - 1].Rid + 1; for (int i = numDefMDs; i < defs.Count; i++) defs[i].Rid = newRid++; // Now we know total table size tableSize = (int)newRid - 1; } else tableSize = defs.Count; if (enableRidToInfo) { ridToInfo = new Dictionary>(defs.Count); foreach (var info in defs) ridToInfo.Add(info.Rid, info); } if ((uint)tableSize > 0x00FFFFFF) throw new ModuleWriterException("Table is too big"); } public int GetCollectionPosition(T def) { return collectionPositions[def]; } } protected override int NumberOfMethods { get { return methodDefInfos.Count; } } public PreserveTokensMetaData(ModuleDef module, UniqueChunkList constants, MethodBodyChunks methodBodies, NetResources netResources, MetaDataOptions options, DebugMetaDataKind debugKind, bool isStandaloneDebugMetadata) : base(module, constants, methodBodies, netResources, options, debugKind, isStandaloneDebugMetadata) { mod = module as ModuleDefMD; if (mod == null) throw new ModuleWriterException("Not a ModuleDefMD"); } /// public override uint GetRid(TypeRef tr) { uint rid; typeRefInfos.TryGetRid(tr, out rid); return rid; } /// public override uint GetRid(TypeDef td) { if (td == null) { Error("TypeDef is null"); return 0; } uint rid; if (typeToRid.TryGetValue(td, out rid)) return rid; Error("TypeDef {0} ({1:X8}) is not defined in this module ({2}). A type was removed that is still referenced by this module.", td, td.MDToken.Raw, module); return 0; } /// public override uint GetRid(FieldDef fd) { uint rid; if (fieldDefInfos.TryGetRid(fd, out rid)) return rid; if (fd == null) Error("Field is null"); else Error("Field {0} ({1:X8}) is not defined in this module ({2}). A field was removed that is still referenced by this module.", fd, fd.MDToken.Raw, module); return 0; } /// public override uint GetRid(MethodDef md) { uint rid; if (methodDefInfos.TryGetRid(md, out rid)) return rid; if (md == null) Error("Method is null"); else Error("Method {0} ({1:X8}) is not defined in this module ({2}). A method was removed that is still referenced by this module.", md, md.MDToken.Raw, module); return 0; } /// public override uint GetRid(ParamDef pd) { uint rid; if (paramDefInfos.TryGetRid(pd, out rid)) return rid; if (pd == null) Error("Param is null"); else Error("Param {0} ({1:X8}) is not defined in this module ({2}). A parameter was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); return 0; } /// public override uint GetRid(MemberRef mr) { uint rid; memberRefInfos.TryGetRid(mr, out rid); return rid; } /// public override uint GetRid(StandAloneSig sas) { uint rid; standAloneSigInfos.TryGetRid(sas, out rid); return rid; } /// public override uint GetRid(EventDef ed) { uint rid; if (eventDefInfos.TryGetRid(ed, out rid)) return rid; if (ed == null) Error("Event is null"); else Error("Event {0} ({1:X8}) is not defined in this module ({2}). An event was removed that is still referenced by this module.", ed, ed.MDToken.Raw, module); return 0; } /// public override uint GetRid(PropertyDef pd) { uint rid; if (propertyDefInfos.TryGetRid(pd, out rid)) return rid; if (pd == null) Error("Property is null"); else Error("Property {0} ({1:X8}) is not defined in this module ({2}). A property was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); return 0; } /// public override uint GetRid(TypeSpec ts) { uint rid; typeSpecInfos.TryGetRid(ts, out rid); return rid; } /// public override uint GetRid(MethodSpec ms) { uint rid; methodSpecInfos.TryGetRid(ms, out rid); return rid; } /// protected override void Initialize() { fieldDefInfos = new MemberDefDict(typeof(FieldDefMD), PreserveFieldRids); methodDefInfos = new MemberDefDict(typeof(MethodDefMD), PreserveMethodRids, true); paramDefInfos = new MemberDefDict(typeof(ParamDefMD), PreserveParamRids); eventDefInfos = new MemberDefDict(typeof(EventDefMD), PreserveEventRids); propertyDefInfos = new MemberDefDict(typeof(PropertyDefMD), PreservePropertyRids); CreateEmptyTableRows(); } /// protected override List GetAllTypeDefs() { if (!PreserveTypeDefRids) { var types2 = new List(module.GetTypes()); InitializeTypeToRid(types2); return types2; } var typeToIndex = new Dictionary(); var types = new List(); uint index = 0; const uint IS_TYPEDEFMD = 0x80000000; const uint INDEX_BITS = 0x00FFFFFF; foreach (var type in module.GetTypes()) { if (type == null) continue; types.Add(type); uint val = (uint)index++; if (type.GetType() == typeof(TypeDefMD)) val |= IS_TYPEDEFMD; typeToIndex[type] = val; } var globalType = types[0]; types.Sort((a, b) => { if (a == b) return 0; // Make sure the global type is always sorted first, even if it's // a TypeDefUser if (a == globalType) return -1; if (b == globalType) return 1; // Sort all TypeDefMDs before all TypeDefUsers uint ai = typeToIndex[a]; uint bi = typeToIndex[b]; bool amd = (ai & IS_TYPEDEFMD) != 0; bool bmd = (bi & IS_TYPEDEFMD) != 0; if (amd == bmd) { // Both are TypeDefMDs or both are TypeDefUsers // If TypeDefMDs, only compare rids since rids are preserved if (amd) return a.Rid.CompareTo(b.Rid); // If TypeDefUsers, rids aren't preserved so compare by index return (ai & INDEX_BITS).CompareTo(bi & INDEX_BITS); } if (amd) return -1; return 1; }); // Some of the original types may have been removed. Create dummy types // so TypeDef rids can be preserved. var newTypes = new List(types.Count); uint prevRid = 1; newTypes.Add(globalType); for (int i = 1; i < types.Count; i++) { var type = types[i]; // TypeDefUsers were sorted last so when we reach one, we can stop if (type.GetType() != typeof(TypeDefMD)) { while (i < types.Count) newTypes.Add(types[i++]); break; } uint currRid = type.Rid; int extraTypes = (int)(currRid - prevRid - 1); if (extraTypes != 0) { // always >= 0 since currRid > prevRid // At least one type has been removed. Create dummy types. for (int j = 0; j < extraTypes; j++) newTypes.Add(new TypeDefUser("dummy", Guid.NewGuid().ToString("B"), module.CorLibTypes.Object.TypeDefOrRef)); } newTypes.Add(type); prevRid = currRid; } InitializeTypeToRid(newTypes); return newTypes; } void InitializeTypeToRid(IEnumerable types) { uint rid = 1; foreach (var type in types) { if (type == null) continue; if (typeToRid.ContainsKey(type)) continue; typeToRid[type] = rid++; } } /// protected override void AllocateTypeDefRids() { foreach (var type in allTypeDefs) { uint rid = tablesHeap.TypeDefTable.Create(new RawTypeDefRow()); if (typeToRid[type] != rid) throw new ModuleWriterException("Got a different rid than expected"); } } /// /// Reserves rows in TypeRef, MemberRef, StandAloneSig, /// TypeSpec and MethodSpec where we will store the original rows /// to make sure they get the same rid. Any user created rows will be stored at /// the end of each table. /// void CreateEmptyTableRows() { uint rows; if (PreserveTypeRefRids) { rows = mod.TablesStream.TypeRefTable.Rows; for (uint i = 0; i < rows; i++) tablesHeap.TypeRefTable.Create(new RawTypeRefRow()); } if (PreserveMemberRefRids) { rows = mod.TablesStream.MemberRefTable.Rows; for (uint i = 0; i < rows; i++) tablesHeap.MemberRefTable.Create(new RawMemberRefRow()); } if (PreserveStandAloneSigRids) { rows = mod.TablesStream.StandAloneSigTable.Rows; for (uint i = 0; i < rows; i++) tablesHeap.StandAloneSigTable.Create(new RawStandAloneSigRow()); } if (PreserveTypeSpecRids) { rows = mod.TablesStream.TypeSpecTable.Rows; for (uint i = 0; i < rows; i++) tablesHeap.TypeSpecTable.Create(new RawTypeSpecRow()); } if (PreserveMethodSpecRids) { rows = mod.TablesStream.MethodSpecTable.Rows; for (uint i = 0; i < rows; i++) tablesHeap.MethodSpecTable.Create(new RawMethodSpecRow()); } } /// /// Adds any non-referenced rows that haven't been added yet but are present in /// the original file. If there are any non-referenced rows, it's usually a sign /// that an obfuscator has encrypted one or more methods or that it has added /// some rows it uses to decrypt something. /// void InitializeUninitializedTableRows() { InitializeTypeRefTableRows(); InitializeMemberRefTableRows(); InitializeStandAloneSigTableRows(); InitializeTypeSpecTableRows(); InitializeMethodSpecTableRows(); } bool initdTypeRef = false; void InitializeTypeRefTableRows() { if (!PreserveTypeRefRids || initdTypeRef) return; initdTypeRef = true; uint rows = mod.TablesStream.TypeRefTable.Rows; for (uint rid = 1; rid <= rows; rid++) AddTypeRef(mod.ResolveTypeRef(rid)); tablesHeap.TypeRefTable.ReAddRows(); } bool initdMemberRef = false; void InitializeMemberRefTableRows() { if (!PreserveMemberRefRids || initdMemberRef) return; initdMemberRef = true; uint rows = mod.TablesStream.MemberRefTable.Rows; for (uint rid = 1; rid <= rows; rid++) AddMemberRef(mod.ResolveMemberRef(rid), true); tablesHeap.MemberRefTable.ReAddRows(); } bool initdStandAloneSig = false; void InitializeStandAloneSigTableRows() { if (!PreserveStandAloneSigRids || initdStandAloneSig) return; initdStandAloneSig = true; uint rows = mod.TablesStream.StandAloneSigTable.Rows; for (uint rid = 1; rid <= rows; rid++) AddStandAloneSig(mod.ResolveStandAloneSig(rid), true); tablesHeap.StandAloneSigTable.ReAddRows(); } bool initdTypeSpec = false; void InitializeTypeSpecTableRows() { if (!PreserveTypeSpecRids || initdTypeSpec) return; initdTypeSpec = true; uint rows = mod.TablesStream.TypeSpecTable.Rows; for (uint rid = 1; rid <= rows; rid++) AddTypeSpec(mod.ResolveTypeSpec(rid), true); tablesHeap.TypeSpecTable.ReAddRows(); } bool initdMethodSpec = false; void InitializeMethodSpecTableRows() { if (!PreserveMethodSpecRids || initdMethodSpec) return; initdMethodSpec = true; uint rows = mod.TablesStream.MethodSpecTable.Rows; for (uint rid = 1; rid <= rows; rid++) AddMethodSpec(mod.ResolveMethodSpec(rid), true); tablesHeap.MethodSpecTable.ReAddRows(); } /// protected override void AllocateMemberDefRids() { FindMemberDefs(); Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids0); for (int i = 1; i <= fieldDefInfos.TableSize; i++) { if ((uint)i != tablesHeap.FieldTable.Create(new RawFieldRow())) throw new ModuleWriterException("Invalid field rid"); } for (int i = 1; i <= methodDefInfos.TableSize; i++) { if ((uint)i != tablesHeap.MethodTable.Create(new RawMethodRow())) throw new ModuleWriterException("Invalid method rid"); } for (int i = 1; i <= paramDefInfos.TableSize; i++) { if ((uint)i != tablesHeap.ParamTable.Create(new RawParamRow())) throw new ModuleWriterException("Invalid param rid"); } for (int i = 1; i <= eventDefInfos.TableSize; i++) { if ((uint)i != tablesHeap.EventTable.Create(new RawEventRow())) throw new ModuleWriterException("Invalid event rid"); } for (int i = 1; i <= propertyDefInfos.TableSize; i++) { if ((uint)i != tablesHeap.PropertyTable.Create(new RawPropertyRow())) throw new ModuleWriterException("Invalid property rid"); } SortFields(); SortMethods(); SortParameters(); SortEvents(); SortProperties(); Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids1); if (fieldDefInfos.NeedPtrTable) { for (int i = 0; i < fieldDefInfos.Count; i++) { var info = fieldDefInfos.GetSorted(i); if ((uint)i + 1 != tablesHeap.FieldPtrTable.Add(new RawFieldPtrRow(info.Rid))) throw new ModuleWriterException("Invalid field ptr rid"); } ReUseDeletedFieldRows(); } if (methodDefInfos.NeedPtrTable) { for (int i = 0; i < methodDefInfos.Count; i++) { var info = methodDefInfos.GetSorted(i); if ((uint)i + 1 != tablesHeap.MethodPtrTable.Add(new RawMethodPtrRow(info.Rid))) throw new ModuleWriterException("Invalid method ptr rid"); } ReUseDeletedMethodRows(); } if (paramDefInfos.NeedPtrTable) { // NOTE: peverify does not support the ParamPtr table. It's a bug. for (int i = 0; i < paramDefInfos.Count; i++) { var info = paramDefInfos.GetSorted(i); if ((uint)i + 1 != tablesHeap.ParamPtrTable.Add(new RawParamPtrRow(info.Rid))) throw new ModuleWriterException("Invalid param ptr rid"); } ReUseDeletedParamRows(); } if (eventDefInfos.NeedPtrTable) { for (int i = 0; i < eventDefInfos.Count; i++) { var info = eventDefInfos.GetSorted(i); if ((uint)i + 1 != tablesHeap.EventPtrTable.Add(new RawEventPtrRow(info.Rid))) throw new ModuleWriterException("Invalid event ptr rid"); } } if (propertyDefInfos.NeedPtrTable) { for (int i = 0; i < propertyDefInfos.Count; i++) { var info = propertyDefInfos.GetSorted(i); if ((uint)i + 1 != tablesHeap.PropertyPtrTable.Add(new RawPropertyPtrRow(info.Rid))) throw new ModuleWriterException("Invalid property ptr rid"); } } Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids2); InitializeMethodAndFieldList(); InitializeParamList(); InitializeEventMap(); InitializePropertyMap(); Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids3); // We must re-use deleted event/property rows after we've initialized // the event/prop map tables. if (eventDefInfos.NeedPtrTable) ReUseDeletedEventRows(); if (propertyDefInfos.NeedPtrTable) ReUseDeletedPropertyRows(); Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids4); InitializeTypeRefTableRows(); InitializeTypeSpecTableRows(); InitializeMemberRefTableRows(); InitializeMethodSpecTableRows(); } /// /// Re-uses all Field rows which aren't owned by any type due to the fields /// having been deleted by the user. The reason we must do this is that the /// FieldPtr and Field tables must be the same size. /// void ReUseDeletedFieldRows() { if (tablesHeap.FieldPtrTable.IsEmpty) return; if (fieldDefInfos.TableSize == tablesHeap.FieldPtrTable.Rows) return; var hasOwner = new bool[fieldDefInfos.TableSize]; for (int i = 0; i < fieldDefInfos.Count; i++) hasOwner[(int)fieldDefInfos.Get(i).Rid - 1] = true; CreateDummyPtrTableType(); uint fieldSig = GetSignature(new FieldSig(module.CorLibTypes.Byte)); for (int i = 0; i < hasOwner.Length; i++) { if (hasOwner[i]) continue; uint frid = (uint)i + 1; var frow = tablesHeap.FieldTable[frid]; frow.Flags = (ushort)(FieldAttributes.Public | FieldAttributes.Static); frow.Name = stringsHeap.Add(string.Format("f{0:X6}", frid)); frow.Signature = fieldSig; tablesHeap.FieldPtrTable.Create(new RawFieldPtrRow(frid)); } if (fieldDefInfos.TableSize != tablesHeap.FieldPtrTable.Rows) throw new ModuleWriterException("Didn't create all dummy fields"); } /// /// Re-uses all Method rows which aren't owned by any type due to the methods /// having been deleted by the user. The reason we must do this is that the /// MethodPtr and Method tables must be the same size. /// void ReUseDeletedMethodRows() { if (tablesHeap.MethodPtrTable.IsEmpty) return; if (methodDefInfos.TableSize == tablesHeap.MethodPtrTable.Rows) return; var hasOwner = new bool[methodDefInfos.TableSize]; for (int i = 0; i < methodDefInfos.Count; i++) hasOwner[(int)methodDefInfos.Get(i).Rid - 1] = true; CreateDummyPtrTableType(); uint methodSig = GetSignature(MethodSig.CreateInstance(module.CorLibTypes.Void)); for (int i = 0; i < hasOwner.Length; i++) { if (hasOwner[i]) continue; uint mrid = (uint)i + 1; var mrow = tablesHeap.MethodTable[mrid]; mrow.RVA = 0; mrow.ImplFlags = (ushort)(MethodImplAttributes.IL | MethodImplAttributes.Managed); mrow.Flags = (ushort)(MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Abstract); mrow.Name = stringsHeap.Add(string.Format("m{0:X6}", mrid)); mrow.Signature = methodSig; mrow.ParamList = (uint)paramDefInfos.Count; tablesHeap.MethodPtrTable.Create(new RawMethodPtrRow(mrid)); } if (methodDefInfos.TableSize != tablesHeap.MethodPtrTable.Rows) throw new ModuleWriterException("Didn't create all dummy methods"); } /// /// Re-uses all Param rows which aren't owned by any type due to the params /// having been deleted by the user. The reason we must do this is that the /// ParamPtr and Param tables must be the same size. /// This method must be called after since /// this method will create more methods at the end of the Method table. /// void ReUseDeletedParamRows() { if (tablesHeap.ParamPtrTable.IsEmpty) return; if (paramDefInfos.TableSize == tablesHeap.ParamPtrTable.Rows) return; var hasOwner = new bool[paramDefInfos.TableSize]; for (int i = 0; i < paramDefInfos.Count; i++) hasOwner[(int)paramDefInfos.Get(i).Rid - 1] = true; CreateDummyPtrTableType(); // For each param, attach it to a new method. Another alternative would be to create // one (or a few) methods with tons of parameters. uint methodSig = GetSignature(MethodSig.CreateInstance(module.CorLibTypes.Void)); for (int i = 0; i < hasOwner.Length; i++) { if (hasOwner[i]) continue; uint prid = (uint)i + 1; var prow = tablesHeap.ParamTable[prid]; prow.Flags = 0; prow.Sequence = 0; // Return type parameter prow.Name = stringsHeap.Add(string.Format("p{0:X6}", prid)); uint ptrRid = tablesHeap.ParamPtrTable.Create(new RawParamPtrRow(prid)); var mrow = new RawMethodRow(0, (ushort)(MethodImplAttributes.IL | MethodImplAttributes.Managed), (ushort)(MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Abstract), stringsHeap.Add(string.Format("mp{0:X6}", prid)), methodSig, ptrRid); uint mrid = tablesHeap.MethodTable.Create(mrow); if (tablesHeap.MethodPtrTable.Rows > 0) tablesHeap.MethodPtrTable.Create(new RawMethodPtrRow(mrid)); } if (paramDefInfos.TableSize != tablesHeap.ParamPtrTable.Rows) throw new ModuleWriterException("Didn't create all dummy params"); } /// /// Re-uses all Event rows which aren't owned by any type due to the events /// having been deleted by the user. The reason we must do this is that the /// EventPtr and Event tables must be the same size. /// void ReUseDeletedEventRows() { if (tablesHeap.EventPtrTable.IsEmpty) return; if (eventDefInfos.TableSize == tablesHeap.EventPtrTable.Rows) return; var hasOwner = new bool[eventDefInfos.TableSize]; for (int i = 0; i < eventDefInfos.Count; i++) hasOwner[(int)eventDefInfos.Get(i).Rid - 1] = true; uint typeRid = CreateDummyPtrTableType(); tablesHeap.EventMapTable.Create(new RawEventMapRow(typeRid, (uint)tablesHeap.EventPtrTable.Rows + 1)); uint eventType = AddTypeDefOrRef(module.CorLibTypes.Object.TypeDefOrRef); for (int i = 0; i < hasOwner.Length; i++) { if (hasOwner[i]) continue; uint erid = (uint)i + 1; var frow = tablesHeap.EventTable[erid]; frow.EventFlags = 0; frow.Name = stringsHeap.Add(string.Format("E{0:X6}", erid)); frow.EventType = eventType; tablesHeap.EventPtrTable.Create(new RawEventPtrRow(erid)); } if (eventDefInfos.TableSize != tablesHeap.EventPtrTable.Rows) throw new ModuleWriterException("Didn't create all dummy events"); } /// /// Re-uses all Property rows which aren't owned by any type due to the properties /// having been deleted by the user. The reason we must do this is that the /// PropertyPtr and Property tables must be the same size. /// void ReUseDeletedPropertyRows() { if (tablesHeap.PropertyPtrTable.IsEmpty) return; if (propertyDefInfos.TableSize == tablesHeap.PropertyPtrTable.Rows) return; var hasOwner = new bool[propertyDefInfos.TableSize]; for (int i = 0; i < propertyDefInfos.Count; i++) hasOwner[(int)propertyDefInfos.Get(i).Rid - 1] = true; uint typeRid = CreateDummyPtrTableType(); tablesHeap.PropertyMapTable.Create(new RawPropertyMapRow(typeRid, (uint)tablesHeap.PropertyPtrTable.Rows + 1)); uint propertySig = GetSignature(PropertySig.CreateStatic(module.CorLibTypes.Object)); for (int i = 0; i < hasOwner.Length; i++) { if (hasOwner[i]) continue; uint prid = (uint)i + 1; var frow = tablesHeap.PropertyTable[prid]; frow.PropFlags = 0; frow.Name = stringsHeap.Add(string.Format("P{0:X6}", prid)); frow.Type = propertySig; tablesHeap.PropertyPtrTable.Create(new RawPropertyPtrRow(prid)); } if (propertyDefInfos.TableSize != tablesHeap.PropertyPtrTable.Rows) throw new ModuleWriterException("Didn't create all dummy properties"); } /// /// Creates a dummy TypeDef at the end of the TypeDef table that will own /// dummy methods and fields. These dummy methods and fields are only created if the size /// of the ptr table is less than the size of the non-ptr table (eg. size MethodPtr table /// is less than size Method table). The only reason the ptr table would be smaller than /// the non-ptr table is when some field/method has been deleted and we must preserve /// all method/field rids. /// uint CreateDummyPtrTableType() { if (dummyPtrTableTypeRid != 0) return dummyPtrTableTypeRid; var flags = TypeAttributes.NotPublic | TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.Abstract | TypeAttributes.AnsiClass; int numFields = fieldDefInfos.NeedPtrTable ? fieldDefInfos.Count : fieldDefInfos.TableSize; int numMethods = methodDefInfos.NeedPtrTable ? methodDefInfos.Count : methodDefInfos.TableSize; var row = new RawTypeDefRow((uint)flags, stringsHeap.Add(Guid.NewGuid().ToString("B")), stringsHeap.Add("dummy_ptr"), AddTypeDefOrRef(module.CorLibTypes.Object.TypeDefOrRef), (uint)numFields + 1, (uint)numMethods + 1); dummyPtrTableTypeRid = tablesHeap.TypeDefTable.Create(row); if (dummyPtrTableTypeRid == 1) throw new ModuleWriterException("Dummy ptr type is the first type"); return dummyPtrTableTypeRid; } uint dummyPtrTableTypeRid; void FindMemberDefs() { var added = new Dictionary(); int pos; foreach (var type in allTypeDefs) { if (type == null) continue; pos = 0; foreach (var field in type.Fields) { if (field == null) continue; fieldDefInfos.Add(field, pos++); } pos = 0; foreach (var method in type.Methods) { if (method == null) continue; methodDefInfos.Add(method, pos++); } pos = 0; foreach (var evt in type.Events) { if (evt == null || added.ContainsKey(evt)) continue; added[evt] = true; eventDefInfos.Add(evt, pos++); } pos = 0; foreach (var prop in type.Properties) { if (prop == null || added.ContainsKey(prop)) continue; added[prop] = true; propertyDefInfos.Add(prop, pos++); } } fieldDefInfos.SortDefs(); methodDefInfos.SortDefs(); eventDefInfos.SortDefs(); propertyDefInfos.SortDefs(); for (int i = 0; i < methodDefInfos.Count; i++) { var method = methodDefInfos.Get(i).Def; pos = 0; foreach (var param in Sort(method.ParamDefs)) { if (param == null) continue; paramDefInfos.Add(param, pos++); } } paramDefInfos.SortDefs(); } void SortFields() { fieldDefInfos.Sort((a, b) => { var dta = a.Def.DeclaringType == null ? 0 : typeToRid[a.Def.DeclaringType]; var dtb = b.Def.DeclaringType == null ? 0 : typeToRid[b.Def.DeclaringType]; if (dta == 0 || dtb == 0) return a.Rid.CompareTo(b.Rid); if (dta != dtb) return dta.CompareTo(dtb); return fieldDefInfos.GetCollectionPosition(a.Def).CompareTo(fieldDefInfos.GetCollectionPosition(b.Def)); }); } void SortMethods() { methodDefInfos.Sort((a, b) => { var dta = a.Def.DeclaringType == null ? 0 : typeToRid[a.Def.DeclaringType]; var dtb = b.Def.DeclaringType == null ? 0 : typeToRid[b.Def.DeclaringType]; if (dta == 0 || dtb == 0) return a.Rid.CompareTo(b.Rid); if (dta != dtb) return dta.CompareTo(dtb); return methodDefInfos.GetCollectionPosition(a.Def).CompareTo(methodDefInfos.GetCollectionPosition(b.Def)); }); } void SortParameters() { paramDefInfos.Sort((a, b) => { var dma = a.Def.DeclaringMethod == null ? 0 : methodDefInfos.Rid(a.Def.DeclaringMethod); var dmb = b.Def.DeclaringMethod == null ? 0 : methodDefInfos.Rid(b.Def.DeclaringMethod); if (dma == 0 || dmb == 0) return a.Rid.CompareTo(b.Rid); if (dma != dmb) return dma.CompareTo(dmb); return paramDefInfos.GetCollectionPosition(a.Def).CompareTo(paramDefInfos.GetCollectionPosition(b.Def)); }); } void SortEvents() { eventDefInfos.Sort((a, b) => { var dta = a.Def.DeclaringType == null ? 0 : typeToRid[a.Def.DeclaringType]; var dtb = b.Def.DeclaringType == null ? 0 : typeToRid[b.Def.DeclaringType]; if (dta == 0 || dtb == 0) return a.Rid.CompareTo(b.Rid); if (dta != dtb) return dta.CompareTo(dtb); return eventDefInfos.GetCollectionPosition(a.Def).CompareTo(eventDefInfos.GetCollectionPosition(b.Def)); }); } void SortProperties() { propertyDefInfos.Sort((a, b) => { var dta = a.Def.DeclaringType == null ? 0 : typeToRid[a.Def.DeclaringType]; var dtb = b.Def.DeclaringType == null ? 0 : typeToRid[b.Def.DeclaringType]; if (dta == 0 || dtb == 0) return a.Rid.CompareTo(b.Rid); if (dta != dtb) return dta.CompareTo(dtb); return propertyDefInfos.GetCollectionPosition(a.Def).CompareTo(propertyDefInfos.GetCollectionPosition(b.Def)); }); } void InitializeMethodAndFieldList() { uint fieldList = 1, methodList = 1; foreach (var type in allTypeDefs) { var typeRow = tablesHeap.TypeDefTable[typeToRid[type]]; typeRow.FieldList = fieldList; typeRow.MethodList = methodList; fieldList += (uint)type.Fields.Count; methodList += (uint)type.Methods.Count; } } void InitializeParamList() { uint ridList = 1; for (uint methodRid = 1; methodRid <= methodDefInfos.TableSize; methodRid++) { var methodInfo = methodDefInfos.GetByRid(methodRid); var row = tablesHeap.MethodTable[methodRid]; row.ParamList = ridList; if (methodInfo != null) ridList += (uint)methodInfo.Def.ParamDefs.Count; } } void InitializeEventMap() { if (!tablesHeap.EventMapTable.IsEmpty) throw new ModuleWriterException("EventMap table isn't empty"); TypeDef type = null; for (int i = 0; i < eventDefInfos.Count; i++) { var info = eventDefInfos.GetSorted(i); if (type == info.Def.DeclaringType) continue; type = info.Def.DeclaringType; var row = new RawEventMapRow(typeToRid[type], info.NewRid); uint eventMapRid = tablesHeap.EventMapTable.Create(row); eventMapInfos.Add(type, eventMapRid); } } void InitializePropertyMap() { if (!tablesHeap.PropertyMapTable.IsEmpty) throw new ModuleWriterException("PropertyMap table isn't empty"); TypeDef type = null; for (int i = 0; i < propertyDefInfos.Count; i++) { var info = propertyDefInfos.GetSorted(i); if (type == info.Def.DeclaringType) continue; type = info.Def.DeclaringType; var row = new RawPropertyMapRow(typeToRid[type], info.NewRid); uint propertyMapRid = tablesHeap.PropertyMapTable.Create(row); propertyMapInfos.Add(type, propertyMapRid); } } /// protected override uint AddTypeRef(TypeRef tr) { if (tr == null) { Error("TypeRef is null"); return 0; } uint rid; if (typeRefInfos.TryGetRid(tr, out rid)) { if (rid == 0) Error("TypeRef {0:X8} has an infinite ResolutionScope loop", tr.MDToken.Raw); return rid; } typeRefInfos.Add(tr, 0); // Prevent inf recursion bool isOld = PreserveTypeRefRids && mod.ResolveTypeRef(tr.Rid) == tr; var row = isOld ? tablesHeap.TypeRefTable[tr.Rid] : new RawTypeRefRow(); row.ResolutionScope = AddResolutionScope(tr.ResolutionScope); row.Name = stringsHeap.Add(tr.Name); row.Namespace = stringsHeap.Add(tr.Namespace); rid = isOld ? tr.Rid : tablesHeap.TypeRefTable.Add(row); typeRefInfos.SetRid(tr, rid); AddCustomAttributes(Table.TypeRef, rid, tr); AddCustomDebugInformationList(Table.TypeRef, rid, tr); return rid; } /// protected override uint AddTypeSpec(TypeSpec ts) { return AddTypeSpec(ts, false); } uint AddTypeSpec(TypeSpec ts, bool forceIsOld) { if (ts == null) { Error("TypeSpec is null"); return 0; } uint rid; if (typeSpecInfos.TryGetRid(ts, out rid)) { if (rid == 0) Error("TypeSpec {0:X8} has an infinite TypeSig loop", ts.MDToken.Raw); return rid; } typeSpecInfos.Add(ts, 0); // Prevent inf recursion bool isOld = forceIsOld || (PreserveTypeSpecRids && mod.ResolveTypeSpec(ts.Rid) == ts); var row = isOld ? tablesHeap.TypeSpecTable[ts.Rid] : new RawTypeSpecRow(); row.Signature = GetSignature(ts.TypeSig, ts.ExtraData); rid = isOld ? ts.Rid : tablesHeap.TypeSpecTable.Add(row); typeSpecInfos.SetRid(ts, rid); AddCustomAttributes(Table.TypeSpec, rid, ts); AddCustomDebugInformationList(Table.TypeSpec, rid, ts); return rid; } /// protected override uint AddMemberRef(MemberRef mr) { return AddMemberRef(mr, false); } uint AddMemberRef(MemberRef mr, bool forceIsOld) { if (mr == null) { Error("MemberRef is null"); return 0; } uint rid; if (memberRefInfos.TryGetRid(mr, out rid)) return rid; bool isOld = forceIsOld || (PreserveMemberRefRids && mod.ResolveMemberRef(mr.Rid) == mr); var row = isOld ? tablesHeap.MemberRefTable[mr.Rid] : new RawMemberRefRow(); row.Class = AddMemberRefParent(mr.Class); row.Name = stringsHeap.Add(mr.Name); row.Signature = GetSignature(mr.Signature); rid = isOld ? mr.Rid : tablesHeap.MemberRefTable.Add(row); memberRefInfos.Add(mr, rid); AddCustomAttributes(Table.MemberRef, rid, mr); AddCustomDebugInformationList(Table.MemberRef, rid, mr); return rid; } /// protected override uint AddStandAloneSig(StandAloneSig sas) { return AddStandAloneSig(sas, false); } uint AddStandAloneSig(StandAloneSig sas, bool forceIsOld) { if (sas == null) { Error("StandAloneSig is null"); return 0; } uint rid; if (standAloneSigInfos.TryGetRid(sas, out rid)) return rid; bool isOld = forceIsOld || (PreserveStandAloneSigRids && mod.ResolveStandAloneSig(sas.Rid) == sas); var row = isOld ? tablesHeap.StandAloneSigTable[sas.Rid] : new RawStandAloneSigRow(); row.Signature = GetSignature(sas.Signature); rid = isOld ? sas.Rid : tablesHeap.StandAloneSigTable.Add(row); standAloneSigInfos.Add(sas, rid); AddCustomAttributes(Table.StandAloneSig, rid, sas); AddCustomDebugInformationList(Table.StandAloneSig, rid, sas); return rid; } /// public override MDToken GetToken(IList locals, uint origToken) { if (!PreserveStandAloneSigRids || !IsValidStandAloneSigToken(origToken)) return base.GetToken(locals, origToken); uint rid = AddStandAloneSig(new LocalSig(locals, false), origToken); if (rid == 0) return base.GetToken(locals, origToken); return new MDToken(Table.StandAloneSig, rid); } /// protected override uint AddStandAloneSig(MethodSig methodSig, uint origToken) { if (!PreserveStandAloneSigRids || !IsValidStandAloneSigToken(origToken)) return base.AddStandAloneSig(methodSig, origToken); uint rid = AddStandAloneSig(methodSig, origToken); if (rid == 0) return base.AddStandAloneSig(methodSig, origToken); return rid; } /// protected override uint AddStandAloneSig(FieldSig fieldSig, uint origToken) { if (!PreserveStandAloneSigRids || !IsValidStandAloneSigToken(origToken)) return base.AddStandAloneSig(fieldSig, origToken); uint rid = AddStandAloneSig(fieldSig, origToken); if (rid == 0) return base.AddStandAloneSig(fieldSig, origToken); return rid; } uint AddStandAloneSig(CallingConventionSig callConvSig, uint origToken) { uint sig = GetSignature(callConvSig); uint otherSig; if (callConvTokenToSignature.TryGetValue(origToken, out otherSig)) { if (sig == otherSig) return MDToken.ToRID(origToken); Warning("Could not preserve StandAloneSig token {0:X8}", origToken); return 0; } uint rid = MDToken.ToRID(origToken); var sas = mod.ResolveStandAloneSig(rid); if (standAloneSigInfos.Exists(sas)) { Warning("StandAloneSig {0:X8} already exists", origToken); return 0; } // Make sure it uses the updated sig var oldSig = sas.Signature; try { sas.Signature = callConvSig; AddStandAloneSig(sas, true); } finally { sas.Signature = oldSig; } callConvTokenToSignature.Add(origToken, sig); return MDToken.ToRID(origToken); } bool IsValidStandAloneSigToken(uint token) { if (MDToken.ToTable(token) != Table.StandAloneSig) return false; uint rid = MDToken.ToRID(token); return mod.TablesStream.StandAloneSigTable.IsValidRID(rid); } /// protected override uint AddMethodSpec(MethodSpec ms) { return AddMethodSpec(ms, false); } uint AddMethodSpec(MethodSpec ms, bool forceIsOld) { if (ms == null) { Error("MethodSpec is null"); return 0; } uint rid; if (methodSpecInfos.TryGetRid(ms, out rid)) return rid; bool isOld = forceIsOld || (PreserveMethodSpecRids && mod.ResolveMethodSpec(ms.Rid) == ms); var row = isOld ? tablesHeap.MethodSpecTable[ms.Rid] : new RawMethodSpecRow(); row.Method = AddMethodDefOrRef(ms.Method); row.Instantiation = GetSignature(ms.Instantiation); rid = isOld ? ms.Rid : tablesHeap.MethodSpecTable.Add(row); methodSpecInfos.Add(ms, rid); AddCustomAttributes(Table.MethodSpec, rid, ms); AddCustomDebugInformationList(Table.MethodSpec, rid, ms); return rid; } /// protected override void BeforeSortingCustomAttributes() { InitializeUninitializedTableRows(); } } } dnlib-2.1_VS2010/src/DotNet/Writer/RelocDirectory.cs000066400000000000000000000070451325033663500221130ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Relocations directory /// public sealed class RelocDirectory : IChunk { readonly Machine machine; readonly List allRelocRvas = new List(); readonly List> relocSections = new List>(); bool isReadOnly; FileOffset offset; RVA rva; uint totalSize; struct RelocInfo { public readonly IChunk Chunk; public readonly uint OffsetOrRva; public RelocInfo(IChunk chunk, uint offset) { Chunk = chunk; OffsetOrRva = offset; } } /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } internal bool NeedsRelocSection { get { return allRelocRvas.Count != 0; } } /// /// Constructor /// /// Machine public RelocDirectory(Machine machine) { this.machine = machine; } /// public void SetOffset(FileOffset offset, RVA rva) { isReadOnly = true; this.offset = offset; this.rva = rva; var allRvas = new List(allRelocRvas.Count); foreach (var info in allRelocRvas) { uint relocRva; if (info.Chunk != null) relocRva = (uint)info.Chunk.RVA + info.OffsetOrRva; else relocRva = info.OffsetOrRva; allRvas.Add(relocRva); } allRvas.Sort(); uint prevPage = uint.MaxValue; List pageList = null; foreach (var relocRva in allRvas) { uint page = relocRva & ~0xFFFU; if (page != prevPage) { prevPage = page; if (pageList != null) totalSize += (uint)(8 + ((pageList.Count + 1) & ~1) * 2); pageList = new List(); relocSections.Add(pageList); } pageList.Add(relocRva); } if (pageList != null) totalSize += (uint)(8 + ((pageList.Count + 1) & ~1) * 2); } /// public uint GetFileLength() { return totalSize; } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { bool is64bit = machine == Machine.AMD64 || machine == Machine.IA64 || machine == Machine.ARM64; // 3 = IMAGE_REL_BASED_HIGHLOW, A = IMAGE_REL_BASED_DIR64 uint relocType = is64bit ? 0xA000U : 0x3000; foreach (var pageList in relocSections) { writer.Write(pageList[0] & ~0xFFFU); writer.Write((uint)(8 + ((pageList.Count + 1) & ~1) * 2)); foreach (var rva in pageList) writer.Write((ushort)(relocType | (rva & 0xFFF))); if ((pageList.Count & 1) != 0) writer.Write((ushort)0); } } /// /// Adds a relocation /// /// RVA of location public void Add(RVA rva) { if (isReadOnly) throw new InvalidOperationException("Can't add a relocation when the relocs section is read-only"); allRelocRvas.Add(new RelocInfo(null, (uint)rva)); } /// /// Adds a relocation /// /// Chunk or null. If it's null, is the RVA /// Offset relative to the start of , or if is null, this is the RVA public void Add(IChunk chunk, uint offset) { if (isReadOnly) throw new InvalidOperationException("Can't add a relocation when the relocs section is read-only"); allRelocRvas.Add(new RelocInfo(chunk, offset)); } } } dnlib-2.1_VS2010/src/DotNet/Writer/SectionSizes.cs000066400000000000000000000040511325033663500215760ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using dnlib.Utils; namespace dnlib.DotNet.Writer { struct SectionSizeInfo { /// /// Length of section /// public readonly uint length; /// /// Section characteristics /// public readonly uint characteristics; /// /// Constructor /// /// Length of section /// Section characteristics public SectionSizeInfo(uint length, uint characteristics) { this.length = length; this.characteristics = characteristics; } } /// /// Calculates the optional header section sizes /// struct SectionSizes { public readonly uint SizeOfHeaders; public readonly uint SizeOfImage; public readonly uint BaseOfData, BaseOfCode; public readonly uint SizeOfCode, SizeOfInitdData, SizeOfUninitdData; public SectionSizes(uint fileAlignment, uint sectionAlignment, uint headerLen, MFunc> getSectionSizeInfos) { SizeOfHeaders = Utils.AlignUp(headerLen, fileAlignment); SizeOfImage = Utils.AlignUp(SizeOfHeaders, sectionAlignment); BaseOfData = 0; BaseOfCode = 0; SizeOfCode = 0; SizeOfInitdData = 0; SizeOfUninitdData = 0; foreach (var section in getSectionSizeInfos()) { uint sectAlignedVs = Utils.AlignUp(section.length, sectionAlignment); uint fileAlignedVs = Utils.AlignUp(section.length, fileAlignment); bool isCode = (section.characteristics & 0x20) != 0; bool isInitdData = (section.characteristics & 0x40) != 0; bool isUnInitdData = (section.characteristics & 0x80) != 0; if (BaseOfCode == 0 && isCode) BaseOfCode = SizeOfImage; if (BaseOfData == 0 && (isInitdData || isUnInitdData)) BaseOfData = SizeOfImage; if (isCode) SizeOfCode += fileAlignedVs; if (isInitdData) SizeOfInitdData += fileAlignedVs; if (isUnInitdData) SizeOfUninitdData += fileAlignedVs; SizeOfImage += sectAlignedVs; } } } } dnlib-2.1_VS2010/src/DotNet/Writer/SerializerMethodContext.cs000066400000000000000000000031421325033663500237730ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; using System.Diagnostics; using dnlib.DotNet.Emit; namespace dnlib.DotNet.Writer { sealed class SerializerMethodContext { readonly Dictionary toOffset; readonly IWriterError helper; MethodDef method; CilBody body; uint bodySize; bool dictInitd; public bool HasBody { get { return body != null; } } public SerializerMethodContext(IWriterError helper) { toOffset = new Dictionary(); this.helper = helper; } internal void SetBody(MethodDef method) { if (this.method != method) { toOffset.Clear(); this.method = method; this.body = method == null ? null : method.Body; dictInitd = false; } } public uint GetOffset(Instruction instr) { if (!dictInitd) { Debug.Assert(body != null); if (body == null) return 0; InitializeDict(); } if (instr == null) return bodySize; uint offset; if (toOffset.TryGetValue(instr, out offset)) return offset; helper.Error("Couldn't find an instruction, maybe it was removed. It's still being referenced by some code or by the PDB"); return bodySize; } public bool IsSameMethod(MethodDef method) { return this.method == method; } void InitializeDict() { Debug.Assert(body != null); Debug.Assert(toOffset.Count == 0); uint offset = 0; var instrs = body.Instructions; for(int i = 0; i < instrs.Count; i++) { var instr = instrs[i]; toOffset[instr] = offset; offset += (uint)instr.GetSize(); } bodySize = offset; dictInitd = true; } } } dnlib-2.1_VS2010/src/DotNet/Writer/SignatureWriter.cs000066400000000000000000000227571325033663500223270ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; namespace dnlib.DotNet.Writer { /// /// Helps map s to tokens /// public interface ISignatureWriterHelper : IWriterError { /// /// Returns a TypeDefOrRef encoded token /// /// A TypeDefOrRef type uint ToEncodedToken(ITypeDefOrRef typeDefOrRef); } /// /// Writes signatures /// public struct SignatureWriter : IDisposable { readonly ISignatureWriterHelper helper; RecursionCounter recursionCounter; readonly MemoryStream outStream; readonly BinaryWriter writer; readonly bool disposeStream; /// /// Write a signature /// /// Helper /// The type /// The signature as a byte array public static byte[] Write(ISignatureWriterHelper helper, TypeSig typeSig) { using (var writer = new SignatureWriter(helper)) { writer.Write(typeSig); return writer.GetResult(); } } internal static byte[] Write(ISignatureWriterHelper helper, TypeSig typeSig, BinaryWriterContext context) { using (var writer = new SignatureWriter(helper, context)) { writer.Write(typeSig); return writer.GetResult(); } } /// /// Write a signature /// /// Helper /// The signature /// The signature as a byte array public static byte[] Write(ISignatureWriterHelper helper, CallingConventionSig sig) { using (var writer = new SignatureWriter(helper)) { writer.Write(sig); return writer.GetResult(); } } internal static byte[] Write(ISignatureWriterHelper helper, CallingConventionSig sig, BinaryWriterContext context) { using (var writer = new SignatureWriter(helper, context)) { writer.Write(sig); return writer.GetResult(); } } SignatureWriter(ISignatureWriterHelper helper) { this.helper = helper; this.recursionCounter = new RecursionCounter(); this.outStream = new MemoryStream(); this.writer = new BinaryWriter(outStream); this.disposeStream = true; } SignatureWriter(ISignatureWriterHelper helper, BinaryWriterContext context) { this.helper = helper; this.recursionCounter = new RecursionCounter(); this.outStream = context.OutStream; this.writer = context.Writer; this.disposeStream = false; outStream.SetLength(0); outStream.Position = 0; } byte[] GetResult() { return outStream.ToArray(); } uint WriteCompressedUInt32(uint value) { return writer.WriteCompressedUInt32(helper, value); } int WriteCompressedInt32(int value) { return writer.WriteCompressedInt32(helper, value); } void Write(TypeSig typeSig) { const ElementType DEFAULT_ELEMENT_TYPE = ElementType.Boolean; if (typeSig == null) { helper.Error("TypeSig is null"); writer.Write((byte)DEFAULT_ELEMENT_TYPE); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); writer.Write((byte)DEFAULT_ELEMENT_TYPE); return; } uint count; switch (typeSig.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: case ElementType.Sentinel: writer.Write((byte)typeSig.ElementType); break; case ElementType.Ptr: case ElementType.ByRef: case ElementType.SZArray: case ElementType.Pinned: writer.Write((byte)typeSig.ElementType); Write(typeSig.Next); break; case ElementType.ValueType: case ElementType.Class: writer.Write((byte)typeSig.ElementType); Write(((TypeDefOrRefSig)typeSig).TypeDefOrRef); break; case ElementType.Var: case ElementType.MVar: writer.Write((byte)typeSig.ElementType); WriteCompressedUInt32(((GenericSig)typeSig).Number); break; case ElementType.Array: writer.Write((byte)typeSig.ElementType); var ary = (ArraySig)typeSig; Write(ary.Next); WriteCompressedUInt32(ary.Rank); if (ary.Rank == 0) break; count = WriteCompressedUInt32((uint)ary.Sizes.Count); for (uint i = 0; i < count; i++) WriteCompressedUInt32(ary.Sizes[(int)i]); count = WriteCompressedUInt32((uint)ary.LowerBounds.Count); for (uint i = 0; i < count; i++) WriteCompressedInt32(ary.LowerBounds[(int)i]); break; case ElementType.GenericInst: writer.Write((byte)typeSig.ElementType); var gis = (GenericInstSig)typeSig; Write(gis.GenericType); count = WriteCompressedUInt32((uint)gis.GenericArguments.Count); for (uint i = 0; i < count; i++) Write(gis.GenericArguments[(int)i]); break; case ElementType.ValueArray: writer.Write((byte)typeSig.ElementType); Write(typeSig.Next); WriteCompressedUInt32((typeSig as ValueArraySig).Size); break; case ElementType.FnPtr: writer.Write((byte)typeSig.ElementType); Write((typeSig as FnPtrSig).Signature); break; case ElementType.CModReqd: case ElementType.CModOpt: writer.Write((byte)typeSig.ElementType); Write((typeSig as ModifierSig).Modifier); Write(typeSig.Next); break; case ElementType.Module: writer.Write((byte)typeSig.ElementType); WriteCompressedUInt32((typeSig as ModuleSig).Index); Write(typeSig.Next); break; case ElementType.End: case ElementType.R: case ElementType.Internal: default: helper.Error("Unknown or unsupported element type"); writer.Write((byte)DEFAULT_ELEMENT_TYPE); break; } recursionCounter.Decrement(); } void Write(ITypeDefOrRef tdr) { if (tdr == null) { helper.Error("TypeDefOrRef is null"); WriteCompressedUInt32(0); return; } uint encodedToken = helper.ToEncodedToken(tdr); if (encodedToken > 0x1FFFFFFF) { helper.Error("Encoded token doesn't fit in 29 bits"); encodedToken = 0; } WriteCompressedUInt32(encodedToken); } void Write(CallingConventionSig sig) { if (sig == null) { helper.Error("sig is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } MethodBaseSig mbs; FieldSig fs; LocalSig ls; GenericInstMethodSig gim; if ((mbs = sig as MethodBaseSig) != null) Write(mbs); else if ((fs = sig as FieldSig) != null) Write(fs); else if ((ls = sig as LocalSig) != null) Write(ls); else if ((gim = sig as GenericInstMethodSig) != null) Write(gim); else { helper.Error("Unknown calling convention sig"); writer.Write((byte)sig.GetCallingConvention()); } recursionCounter.Decrement(); } void Write(MethodBaseSig sig) { if (sig == null) { helper.Error("sig is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } writer.Write((byte)sig.GetCallingConvention()); if (sig.Generic) WriteCompressedUInt32(sig.GenParamCount); uint numParams = (uint)sig.Params.Count; if (sig.ParamsAfterSentinel != null) numParams += (uint)sig.ParamsAfterSentinel.Count; uint count = WriteCompressedUInt32(numParams); Write(sig.RetType); for (uint i = 0; i < count && i < (uint)sig.Params.Count; i++) Write(sig.Params[(int)i]); if (sig.ParamsAfterSentinel != null && sig.ParamsAfterSentinel.Count > 0) { writer.Write((byte)ElementType.Sentinel); for (uint i = 0, j = (uint)sig.Params.Count; i < (uint)sig.ParamsAfterSentinel.Count && j < count; i++, j++) Write(sig.ParamsAfterSentinel[(int)i]); } recursionCounter.Decrement(); } void Write(FieldSig sig) { if (sig == null) { helper.Error("sig is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } writer.Write((byte)sig.GetCallingConvention()); Write(sig.Type); recursionCounter.Decrement(); } void Write(LocalSig sig) { if (sig == null) { helper.Error("sig is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } writer.Write((byte)sig.GetCallingConvention()); uint count = WriteCompressedUInt32((uint)sig.Locals.Count); if (count >= 0x10000) { // ldloc 0xFFFF is invalid, see the ldloc documentation helper.Error("Too many locals, max number of locals is 65535 (0xFFFF)"); } for (uint i = 0; i < count; i++) Write(sig.Locals[(int)i]); recursionCounter.Decrement(); } void Write(GenericInstMethodSig sig) { if (sig == null) { helper.Error("sig is null"); return; } if (!recursionCounter.Increment()) { helper.Error("Infinite recursion"); return; } writer.Write((byte)sig.GetCallingConvention()); uint count = WriteCompressedUInt32((uint)sig.GenericArguments.Count); for (uint i = 0; i < count; i++) Write(sig.GenericArguments[(int)i]); recursionCounter.Decrement(); } /// public void Dispose() { if (!disposeStream) return; if (outStream != null) outStream.Dispose(); if (writer != null) ((IDisposable)writer).Dispose(); } } } dnlib-2.1_VS2010/src/DotNet/Writer/StartupStub.cs000066400000000000000000000051341325033663500214570ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Stores the instruction that jumps to _CorExeMain/_CorDllMain /// public sealed class StartupStub : IChunk { const StubType stubType = StubType.EntryPoint; readonly RelocDirectory relocDirectory; readonly Machine machine; readonly CpuArch cpuArch; readonly LogError logError; FileOffset offset; RVA rva; /// /// Gets/sets the /// public ImportDirectory ImportDirectory { get; set; } /// /// Gets/sets the /// public PEHeaders PEHeaders { get; set; } /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Gets the address of the JMP instruction /// public RVA EntryPointRVA { get { return rva + (cpuArch == null ? 0 : cpuArch.GetStubCodeOffset(stubType)); } } internal bool Enable { get; set; } internal uint Alignment { get { return cpuArch == null ? 1 : cpuArch.GetStubAlignment(stubType); } } internal delegate void LogError(string format, params object[] args); /// /// Constructor /// /// Reloc directory /// Machine /// Error logger internal StartupStub(RelocDirectory relocDirectory, Machine machine, LogError logError) { this.relocDirectory = relocDirectory; this.machine = machine; this.logError = logError; CpuArch.TryGetCpuArch(machine, out cpuArch); } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; if (!Enable) return; if (cpuArch == null) { logError("The module needs an unmanaged entry point but the CPU architecture isn't supported: {0} (0x{1:X4})", machine, (ushort)machine); return; } cpuArch.WriteStubRelocs(stubType, relocDirectory, this, 0); } /// public uint GetFileLength() { if (!Enable) return 0; if (cpuArch == null) return 0; return cpuArch.GetStubSize(stubType); } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { if (!Enable) return; if (cpuArch == null) return; cpuArch.WriteStub(stubType, writer, PEHeaders.ImageBase, (uint)rva, (uint)ImportDirectory.IatCorXxxMainRVA); } } } dnlib-2.1_VS2010/src/DotNet/Writer/StringsHeap.cs000066400000000000000000000203351325033663500214060ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.IO; using dnlib.DotNet.MD; using System.Diagnostics; namespace dnlib.DotNet.Writer { /// /// #Strings heap /// public sealed class StringsHeap : HeapBase, IOffsetHeap { readonly Dictionary cachedDict = new Dictionary(UTF8StringEqualityComparer.Instance); readonly List cached = new List(); uint nextOffset = 1; byte[] originalData; Dictionary userRawData; readonly Dictionary toStringsOffsetInfo = new Dictionary(UTF8StringEqualityComparer.Instance); readonly Dictionary offsetIdToInfo = new Dictionary(); readonly List stringsOffsetInfos = new List(); const uint STRINGS_ID_FLAG = 0x80000000; uint stringsId = STRINGS_ID_FLAG | 0; sealed class StringsOffsetInfo { public StringsOffsetInfo(UTF8String value, uint stringsId) { Value = value; StringsId = stringsId; Debug.Assert((stringsId & STRINGS_ID_FLAG) != 0); } public readonly UTF8String Value; public readonly uint StringsId; public uint StringsOffset; public override string ToString() { return string.Format("{0:X8} {1:X4} {2}", StringsId, StringsOffset, Value.String); } } /// public override string Name { get { return "#Strings"; } } /// /// Populates strings from an existing (eg. to preserve /// string offsets) /// /// The #Strings stream with the original content public void Populate(StringsStream stringsStream) { if (isReadOnly) throw new ModuleWriterException("Trying to modify #Strings when it's read-only"); if (originalData != null) throw new InvalidOperationException("Can't call method twice"); if (nextOffset != 1) throw new InvalidOperationException("Add() has already been called"); if (stringsStream == null || stringsStream.ImageStreamLength == 0) return; using (var reader = stringsStream.GetClonedImageStream()) { originalData = reader.ReadAllBytes(); nextOffset = (uint)originalData.Length; Populate(reader); } } void Populate(IImageStream reader) { reader.Position = 1; while (reader.Position < reader.Length) { uint offset = (uint)reader.Position; var bytes = reader.ReadBytesUntilByte(0); if (bytes == null) break; reader.ReadByte(); // terminating zero if (bytes.Length == 0) continue; var s = new UTF8String(bytes); if (!cachedDict.ContainsKey(s)) cachedDict[s] = offset; } } internal void AddOptimizedStrings() { if (isReadOnly) throw new ModuleWriterException("Trying to modify #Strings when it's read-only"); stringsOffsetInfos.Sort(Comparison_StringsOffsetInfoSorter); StringsOffsetInfo prevInfo = null; foreach (var info in stringsOffsetInfos) { if (prevInfo != null && EndsWith(prevInfo.Value, info.Value)) info.StringsOffset = prevInfo.StringsOffset + (uint)(prevInfo.Value.Data.Length - info.Value.Data.Length); else info.StringsOffset = AddToCache(info.Value); prevInfo = info; } } static bool EndsWith(UTF8String s, UTF8String value) { var d = s.Data; var vd = value.Data; int i = d.Length - vd.Length; if (i < 0) return false; for (int vi = 0; vi < vd.Length; vi++) { if (d[i] != vd[vi]) return false; i++; } return true; } static readonly Comparison Comparison_StringsOffsetInfoSorter = StringsOffsetInfoSorter; static int StringsOffsetInfoSorter(StringsOffsetInfo a, StringsOffsetInfo b) { var da = a.Value.Data; var db = b.Value.Data; int ai = da.Length - 1; int bi = db.Length - 1; int len = Math.Min(da.Length, db.Length); while (len > 0) { int c = da[ai] - db[bi]; if (c != 0) return c; ai--; bi--; len--; } return db.Length - da.Length; } /// /// Adds a string to the #Strings heap. The returned value is not necessarily an offset in /// the #Strings heap. Call to get the offset. /// /// The string /// The offset id. This is not a #Strings offset. Call to get the #Strings offset public uint Add(UTF8String s) { if (isReadOnly) throw new ModuleWriterException("Trying to modify #Strings when it's read-only"); if (UTF8String.IsNullOrEmpty(s)) return 0; StringsOffsetInfo info; if (toStringsOffsetInfo.TryGetValue(s, out info)) return info.StringsId; uint offset; if (cachedDict.TryGetValue(s, out offset)) return offset; if (Array.IndexOf(s.Data, (byte)0) >= 0) throw new ArgumentException("Strings in the #Strings heap can't contain NUL bytes"); info = new StringsOffsetInfo(s, stringsId++); Debug.Assert(!toStringsOffsetInfo.ContainsKey(s)); Debug.Assert(!offsetIdToInfo.ContainsKey(info.StringsId)); toStringsOffsetInfo[s] = info; offsetIdToInfo[info.StringsId] = info; stringsOffsetInfos.Add(info); return info.StringsId; } /// /// Gets the offset of a string in the #Strings heap. This method can only be called after /// all strings have been added. /// /// Offset id returned by /// public uint GetOffset(uint offsetId) { if (!isReadOnly) throw new ModuleWriterException("This method can only be called after all strings have been added and this heap is read-only"); if ((offsetId & STRINGS_ID_FLAG) == 0) return offsetId; StringsOffsetInfo info; if (offsetIdToInfo.TryGetValue(offsetId, out info)) { Debug.Assert(info.StringsOffset != 0); return info.StringsOffset; } throw new ArgumentOutOfRangeException("offsetId"); } /// /// Adds a string to the #Strings heap, but does not re-use an existing position /// /// The string /// The offset of the string in the #Strings heap public uint Create(UTF8String s) { if (isReadOnly) throw new ModuleWriterException("Trying to modify #Strings when it's read-only"); if (UTF8String.IsNullOrEmpty(s)) s = UTF8String.Empty; if (Array.IndexOf(s.Data, (byte)0) >= 0) throw new ArgumentException("Strings in the #Strings heap can't contain NUL bytes"); return AddToCache(s); } uint AddToCache(UTF8String s) { uint offset; cached.Add(s); cachedDict[s] = offset = nextOffset; nextOffset += (uint)s.Data.Length + 1; return offset; } /// public override uint GetRawLength() { return nextOffset; } /// protected override void WriteToImpl(BinaryWriter writer) { if (originalData != null) writer.Write(originalData); else writer.Write((byte)0); uint offset = originalData != null ? (uint)originalData.Length : 1; foreach (var s in cached) { byte[] rawData; if (userRawData != null && userRawData.TryGetValue(offset, out rawData)) { if (rawData.Length != s.Data.Length + 1) throw new InvalidOperationException("Invalid length of raw data"); writer.Write(rawData); } else { writer.Write(s.Data); writer.Write((byte)0); } offset += (uint)s.Data.Length + 1; } } /// public int GetRawDataSize(UTF8String data) { return data.Data.Length + 1; } /// public void SetRawData(uint offset, byte[] rawData) { if (rawData == null) throw new ArgumentNullException("rawData"); if (userRawData == null) userRawData = new Dictionary(); userRawData[offset] = rawData; } /// public IEnumerable> GetAllRawData() { uint offset = originalData != null ? (uint)originalData.Length : 1; foreach (var s in cached) { var rawData = new byte[s.Data.Length + 1]; Array.Copy(s.Data, rawData, s.Data.Length); yield return new KeyValuePair(offset, rawData); offset += (uint)rawData.Length; } } } } dnlib-2.1_VS2010/src/DotNet/Writer/StrongNameSignature.cs000066400000000000000000000017651325033663500231240ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Strong name signature chunk /// public sealed class StrongNameSignature : IChunk { FileOffset offset; RVA rva; int size; /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Constructor /// /// Size of strong name signature public StrongNameSignature(int size) { this.size = size; } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } /// public uint GetFileLength() { return (uint)this.size; } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { writer.WriteZeros(size); } } } dnlib-2.1_VS2010/src/DotNet/Writer/TablesHeap.cs000066400000000000000000000512521325033663500211710ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; using dnlib.IO; using dnlib.PE; using dnlib.DotNet.MD; using System; using System.Collections.Generic; namespace dnlib.DotNet.Writer { /// /// options /// public sealed class TablesHeapOptions { /// /// Should be 0 /// public uint? Reserved1; /// /// Major version number. Default is 2. Valid versions are v1.0 (no generics), /// v1.1 (generics are supported), or v2.0 (recommended). /// public byte? MajorVersion; /// /// Minor version number. Default is 0. /// public byte? MinorVersion; /// /// Force #- or #~ stream. Default value is null and recommended because the correct /// tables stream will be used. true will force #- (Edit N' Continue) /// stream, and false will force #~ (normal compressed) stream. /// public bool? UseENC; /// /// Extra data to write /// public uint? ExtraData; /// /// true if there are deleted s, s, /// s, s, s and/or /// s. /// public bool? HasDeletedRows; /// /// Creates portable PDB v1.0 options /// /// public static TablesHeapOptions CreatePortablePdbV1_0() { return new TablesHeapOptions { Reserved1 = 0, MajorVersion = 2, MinorVersion = 0, UseENC = null, ExtraData = null, HasDeletedRows = null, }; } } /// /// Contains all .NET tables /// public sealed class TablesHeap : IHeap { uint length; byte majorVersion; byte minorVersion; bool bigStrings; bool bigGuid; bool bigBlob; bool hasDeletedRows; readonly MetaData metadata; readonly TablesHeapOptions options; FileOffset offset; RVA rva; /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } #pragma warning disable 1591 // XML doc comment public readonly MDTable ModuleTable = new MDTable(Table.Module, RawRowEqualityComparer.Instance); public readonly MDTable TypeRefTable = new MDTable(Table.TypeRef, RawRowEqualityComparer.Instance); public readonly MDTable TypeDefTable = new MDTable(Table.TypeDef, RawRowEqualityComparer.Instance); public readonly MDTable FieldPtrTable = new MDTable(Table.FieldPtr, RawRowEqualityComparer.Instance); public readonly MDTable FieldTable = new MDTable(Table.Field, RawRowEqualityComparer.Instance); public readonly MDTable MethodPtrTable = new MDTable(Table.MethodPtr, RawRowEqualityComparer.Instance); public readonly MDTable MethodTable = new MDTable(Table.Method, RawRowEqualityComparer.Instance); public readonly MDTable ParamPtrTable = new MDTable(Table.ParamPtr, RawRowEqualityComparer.Instance); public readonly MDTable ParamTable = new MDTable(Table.Param, RawRowEqualityComparer.Instance); public readonly MDTable InterfaceImplTable = new MDTable(Table.InterfaceImpl, RawRowEqualityComparer.Instance); public readonly MDTable MemberRefTable = new MDTable(Table.MemberRef, RawRowEqualityComparer.Instance); public readonly MDTable ConstantTable = new MDTable(Table.Constant, RawRowEqualityComparer.Instance); public readonly MDTable CustomAttributeTable = new MDTable(Table.CustomAttribute, RawRowEqualityComparer.Instance); public readonly MDTable FieldMarshalTable = new MDTable(Table.FieldMarshal, RawRowEqualityComparer.Instance); public readonly MDTable DeclSecurityTable = new MDTable(Table.DeclSecurity, RawRowEqualityComparer.Instance); public readonly MDTable ClassLayoutTable = new MDTable(Table.ClassLayout, RawRowEqualityComparer.Instance); public readonly MDTable FieldLayoutTable = new MDTable(Table.FieldLayout, RawRowEqualityComparer.Instance); public readonly MDTable StandAloneSigTable = new MDTable(Table.StandAloneSig, RawRowEqualityComparer.Instance); public readonly MDTable EventMapTable = new MDTable(Table.EventMap, RawRowEqualityComparer.Instance); public readonly MDTable EventPtrTable = new MDTable(Table.EventPtr, RawRowEqualityComparer.Instance); public readonly MDTable EventTable = new MDTable(Table.Event, RawRowEqualityComparer.Instance); public readonly MDTable PropertyMapTable = new MDTable(Table.PropertyMap, RawRowEqualityComparer.Instance); public readonly MDTable PropertyPtrTable = new MDTable(Table.PropertyPtr, RawRowEqualityComparer.Instance); public readonly MDTable PropertyTable = new MDTable(Table.Property, RawRowEqualityComparer.Instance); public readonly MDTable MethodSemanticsTable = new MDTable(Table.MethodSemantics, RawRowEqualityComparer.Instance); public readonly MDTable MethodImplTable = new MDTable(Table.MethodImpl, RawRowEqualityComparer.Instance); public readonly MDTable ModuleRefTable = new MDTable(Table.ModuleRef, RawRowEqualityComparer.Instance); public readonly MDTable TypeSpecTable = new MDTable(Table.TypeSpec, RawRowEqualityComparer.Instance); public readonly MDTable ImplMapTable = new MDTable(Table.ImplMap, RawRowEqualityComparer.Instance); public readonly MDTable FieldRVATable = new MDTable(Table.FieldRVA, RawRowEqualityComparer.Instance); public readonly MDTable ENCLogTable = new MDTable(Table.ENCLog, RawRowEqualityComparer.Instance); public readonly MDTable ENCMapTable = new MDTable(Table.ENCMap, RawRowEqualityComparer.Instance); public readonly MDTable AssemblyTable = new MDTable(Table.Assembly, RawRowEqualityComparer.Instance); public readonly MDTable AssemblyProcessorTable = new MDTable(Table.AssemblyProcessor, RawRowEqualityComparer.Instance); public readonly MDTable AssemblyOSTable = new MDTable(Table.AssemblyOS, RawRowEqualityComparer.Instance); public readonly MDTable AssemblyRefTable = new MDTable(Table.AssemblyRef, RawRowEqualityComparer.Instance); public readonly MDTable AssemblyRefProcessorTable = new MDTable(Table.AssemblyRefProcessor, RawRowEqualityComparer.Instance); public readonly MDTable AssemblyRefOSTable = new MDTable(Table.AssemblyRefOS, RawRowEqualityComparer.Instance); public readonly MDTable FileTable = new MDTable(Table.File, RawRowEqualityComparer.Instance); public readonly MDTable ExportedTypeTable = new MDTable(Table.ExportedType, RawRowEqualityComparer.Instance); public readonly MDTable ManifestResourceTable = new MDTable(Table.ManifestResource, RawRowEqualityComparer.Instance); public readonly MDTable NestedClassTable = new MDTable(Table.NestedClass, RawRowEqualityComparer.Instance); public readonly MDTable GenericParamTable = new MDTable(Table.GenericParam, RawRowEqualityComparer.Instance); public readonly MDTable MethodSpecTable = new MDTable(Table.MethodSpec, RawRowEqualityComparer.Instance); public readonly MDTable GenericParamConstraintTable = new MDTable(Table.GenericParamConstraint, RawRowEqualityComparer.Instance); public readonly MDTable DocumentTable = new MDTable(Table.Document, RawRowEqualityComparer.Instance); public readonly MDTable MethodDebugInformationTable = new MDTable(Table.MethodDebugInformation, RawRowEqualityComparer.Instance); public readonly MDTable LocalScopeTable = new MDTable(Table.LocalScope, RawRowEqualityComparer.Instance); public readonly MDTable LocalVariableTable = new MDTable(Table.LocalVariable, RawRowEqualityComparer.Instance); public readonly MDTable LocalConstantTable = new MDTable(Table.LocalConstant, RawRowEqualityComparer.Instance); public readonly MDTable ImportScopeTable = new MDTable(Table.ImportScope, RawRowEqualityComparer.Instance); public readonly MDTable StateMachineMethodTable = new MDTable(Table.StateMachineMethod, RawRowEqualityComparer.Instance); public readonly MDTable CustomDebugInformationTable = new MDTable(Table.CustomDebugInformation, RawRowEqualityComparer.Instance); #pragma warning restore /// /// All tables /// public readonly IMDTable[] Tables; /// public string Name { get { return IsENC ? "#-" : "#~"; } } /// public bool IsEmpty { get { return false; } } /// /// true if the Edit 'N Continue name will be used (#-) /// public bool IsENC { get { if (options.UseENC.HasValue) return options.UseENC.Value; return hasDeletedRows || !FieldPtrTable.IsEmpty || !MethodPtrTable.IsEmpty || !ParamPtrTable.IsEmpty || !EventPtrTable.IsEmpty || !PropertyPtrTable.IsEmpty || !(InterfaceImplTable.IsEmpty || InterfaceImplTable.IsSorted) || !(ConstantTable.IsEmpty || ConstantTable.IsSorted) || !(CustomAttributeTable.IsEmpty || CustomAttributeTable.IsSorted) || !(FieldMarshalTable.IsEmpty || FieldMarshalTable.IsSorted) || !(DeclSecurityTable.IsEmpty || DeclSecurityTable.IsSorted) || !(ClassLayoutTable.IsEmpty || ClassLayoutTable.IsSorted) || !(FieldLayoutTable.IsEmpty || FieldLayoutTable.IsSorted) || !(EventMapTable.IsEmpty || EventMapTable.IsSorted) || !(PropertyMapTable.IsEmpty || PropertyMapTable.IsSorted) || !(MethodSemanticsTable.IsEmpty || MethodSemanticsTable.IsSorted) || !(MethodImplTable.IsEmpty || MethodImplTable.IsSorted) || !(ImplMapTable.IsEmpty || ImplMapTable.IsSorted) || !(FieldRVATable.IsEmpty || FieldRVATable.IsSorted) || !(NestedClassTable.IsEmpty || NestedClassTable.IsSorted) || !(GenericParamTable.IsEmpty || GenericParamTable.IsSorted) || !(GenericParamConstraintTable.IsEmpty || GenericParamConstraintTable.IsSorted); } } /// /// true if any rows have been deleted (eg. a deleted TypeDef, Method, Field, etc. /// Its name has been renamed to _Deleted). /// public bool HasDeletedRows { get { return hasDeletedRows; } set { hasDeletedRows = value; } } /// /// true if #Strings heap size > 0xFFFF /// public bool BigStrings { get { return bigStrings; } set { bigStrings = value; } } /// /// true if #GUID heap size > 0xFFFF /// public bool BigGuid { get { return bigGuid; } set { bigGuid = value; } } /// /// true if #Blob heap size > 0xFFFF /// public bool BigBlob { get { return bigBlob; } set { bigBlob = value; } } /// /// Constructor /// /// Metadata owner /// Options public TablesHeap(MetaData metadata, TablesHeapOptions options) { this.metadata = metadata; this.options = options ?? new TablesHeapOptions(); this.hasDeletedRows = this.options.HasDeletedRows ?? false; this.Tables = new IMDTable[] { ModuleTable, TypeRefTable, TypeDefTable, FieldPtrTable, FieldTable, MethodPtrTable, MethodTable, ParamPtrTable, ParamTable, InterfaceImplTable, MemberRefTable, ConstantTable, CustomAttributeTable, FieldMarshalTable, DeclSecurityTable, ClassLayoutTable, FieldLayoutTable, StandAloneSigTable, EventMapTable, EventPtrTable, EventTable, PropertyMapTable, PropertyPtrTable, PropertyTable, MethodSemanticsTable, MethodImplTable, ModuleRefTable, TypeSpecTable, ImplMapTable, FieldRVATable, ENCLogTable, ENCMapTable, AssemblyTable, AssemblyProcessorTable, AssemblyOSTable, AssemblyRefTable, AssemblyRefProcessorTable, AssemblyRefOSTable, FileTable, ExportedTypeTable, ManifestResourceTable, NestedClassTable, GenericParamTable, MethodSpecTable, GenericParamConstraintTable, new MDTable((Table)0x2D, RawDummyRow.Comparer), new MDTable((Table)0x2E, RawDummyRow.Comparer), new MDTable((Table)0x2F, RawDummyRow.Comparer), DocumentTable, MethodDebugInformationTable, LocalScopeTable, LocalVariableTable, LocalConstantTable, ImportScopeTable, StateMachineMethodTable, CustomDebugInformationTable, }; } sealed class RawDummyRow : IRawRow { public static readonly IEqualityComparer Comparer = new RawDummyRowEqualityComparer(); sealed class RawDummyRowEqualityComparer : IEqualityComparer { public bool Equals(RawDummyRow x, RawDummyRow y) { throw new NotSupportedException(); } public int GetHashCode(RawDummyRow obj) { throw new NotSupportedException(); } } public uint Read(int index) { throw new NotSupportedException(); } public void Write(int index, uint value) { throw new NotSupportedException(); } } /// public void SetReadOnly() { foreach (var mdt in Tables) mdt.SetReadOnly(); } /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; } /// public uint GetFileLength() { if (length == 0) CalculateLength(); return Utils.AlignUp(length, HeapBase.ALIGNMENT); } /// public uint GetVirtualSize() { return GetFileLength(); } /// /// Calculates the length. This will set all MD tables to read-only. /// public void CalculateLength() { if (length != 0) return; SetReadOnly(); majorVersion = options.MajorVersion ?? 2; minorVersion = options.MinorVersion ?? 0; if (((majorVersion << 8) | minorVersion) <= 0x100) { if (!GenericParamTable.IsEmpty || !MethodSpecTable.IsEmpty || !GenericParamConstraintTable.IsEmpty) throw new ModuleWriterException("Tables heap version <= v1.0 but generic tables are not empty"); } var dnTableSizes = new DotNetTableSizes(); var tableInfos = dnTableSizes.CreateTables(majorVersion, minorVersion); var rowCounts = GetRowCounts(); dnTableSizes.InitializeSizes(bigStrings, bigGuid, bigBlob, systemTables ?? rowCounts, rowCounts); for (int i = 0; i < Tables.Length; i++) Tables[i].TableInfo = tableInfos[i]; length = 24; foreach (var mdt in Tables) { if (mdt.IsEmpty) continue; length += (uint)(4 + mdt.TableInfo.RowSize * mdt.Rows); } if (options.ExtraData.HasValue) length += 4; } uint[] GetRowCounts() { var sizes = new uint[Tables.Length]; for (int i = 0; i < sizes.Length; i++) sizes[i] = (uint)Tables[i].Rows; return sizes; } internal void GetSystemTableRows(out ulong mask, uint[] tables) { if (tables.Length != 0x40) throw new InvalidOperationException(); var tablesMask = GetValidMask(); ulong bit = 1; mask = 0; for (int i = 0; i < 0x40; i++, bit <<= 1) { var table = (Table)i; if (DotNetTableSizes.IsSystemTable(table)) { if ((tablesMask & bit) != 0) { tables[i] = (uint)Tables[i].Rows; mask |= bit; } else tables[i] = 0; } else tables[i] = 0; } } internal void SetSystemTableRows(uint[] systemTables) { this.systemTables = (uint[])systemTables.Clone(); } uint[] systemTables; /// public void WriteTo(BinaryWriter writer) { writer.Write(options.Reserved1 ?? 0); writer.Write(majorVersion); writer.Write(minorVersion); writer.Write((byte)GetMDStreamFlags()); writer.Write(GetLog2Rid()); writer.Write(GetValidMask()); writer.Write(GetSortedMask()); foreach (var mdt in Tables) { if (!mdt.IsEmpty) writer.Write(mdt.Rows); } if (options.ExtraData.HasValue) writer.Write(options.ExtraData.Value); writer.Write(metadata, ModuleTable); writer.Write(metadata, TypeRefTable); writer.Write(metadata, TypeDefTable); writer.Write(metadata, FieldPtrTable); writer.Write(metadata, FieldTable); writer.Write(metadata, MethodPtrTable); writer.Write(metadata, MethodTable); writer.Write(metadata, ParamPtrTable); writer.Write(metadata, ParamTable); writer.Write(metadata, InterfaceImplTable); writer.Write(metadata, MemberRefTable); writer.Write(metadata, ConstantTable); writer.Write(metadata, CustomAttributeTable); writer.Write(metadata, FieldMarshalTable); writer.Write(metadata, DeclSecurityTable); writer.Write(metadata, ClassLayoutTable); writer.Write(metadata, FieldLayoutTable); writer.Write(metadata, StandAloneSigTable); writer.Write(metadata, EventMapTable); writer.Write(metadata, EventPtrTable); writer.Write(metadata, EventTable); writer.Write(metadata, PropertyMapTable); writer.Write(metadata, PropertyPtrTable); writer.Write(metadata, PropertyTable); writer.Write(metadata, MethodSemanticsTable); writer.Write(metadata, MethodImplTable); writer.Write(metadata, ModuleRefTable); writer.Write(metadata, TypeSpecTable); writer.Write(metadata, ImplMapTable); writer.Write(metadata, FieldRVATable); writer.Write(metadata, ENCLogTable); writer.Write(metadata, ENCMapTable); writer.Write(metadata, AssemblyTable); writer.Write(metadata, AssemblyProcessorTable); writer.Write(metadata, AssemblyOSTable); writer.Write(metadata, AssemblyRefTable); writer.Write(metadata, AssemblyRefProcessorTable); writer.Write(metadata, AssemblyRefOSTable); writer.Write(metadata, FileTable); writer.Write(metadata, ExportedTypeTable); writer.Write(metadata, ManifestResourceTable); writer.Write(metadata, NestedClassTable); writer.Write(metadata, GenericParamTable); writer.Write(metadata, MethodSpecTable); writer.Write(metadata, GenericParamConstraintTable); writer.Write(metadata, DocumentTable); writer.Write(metadata, MethodDebugInformationTable); writer.Write(metadata, LocalScopeTable); writer.Write(metadata, LocalVariableTable); writer.Write(metadata, LocalConstantTable); writer.Write(metadata, ImportScopeTable); writer.Write(metadata, StateMachineMethodTable); writer.Write(metadata, CustomDebugInformationTable); writer.WriteZeros((int)(Utils.AlignUp(length, HeapBase.ALIGNMENT) - length)); } MDStreamFlags GetMDStreamFlags() { MDStreamFlags flags = 0; if (bigStrings) flags |= MDStreamFlags.BigStrings; if (bigGuid) flags |= MDStreamFlags.BigGUID; if (bigBlob) flags |= MDStreamFlags.BigBlob; if (options.ExtraData.HasValue) flags |= MDStreamFlags.ExtraData; if (hasDeletedRows) flags |= MDStreamFlags.HasDelete; return flags; } byte GetLog2Rid() { //TODO: Sometimes this is 16. Probably when at least one of the table indexes requires 4 bytes. return 1; } ulong GetValidMask() { ulong mask = 0; foreach (var mdt in Tables) { if (!mdt.IsEmpty) mask |= 1UL << (int)mdt.Table; } return mask; } ulong GetSortedMask() { ulong mask = 0; foreach (var mdt in Tables) { if (mdt.IsSorted) mask |= 1UL << (int)mdt.Table; } return mask; } /// public override string ToString() { return Name; } } } dnlib-2.1_VS2010/src/DotNet/Writer/USHeap.cs000066400000000000000000000120361325033663500203030ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.IO; using dnlib.DotNet.MD; namespace dnlib.DotNet.Writer { /// /// #US heap /// public sealed class USHeap : HeapBase, IOffsetHeap { readonly Dictionary cachedDict = new Dictionary(StringComparer.Ordinal); readonly List cached = new List(); uint nextOffset = 1; byte[] originalData; Dictionary userRawData; /// public override string Name { get { return "#US"; } } /// /// Populates strings from an existing (eg. to preserve /// string tokens) /// /// The #US stream with the original content public void Populate(USStream usStream) { if (originalData != null) throw new InvalidOperationException("Can't call method twice"); if (nextOffset != 1) throw new InvalidOperationException("Add() has already been called"); if (usStream == null || usStream.ImageStreamLength == 0) return; using (var reader = usStream.GetClonedImageStream()) { originalData = reader.ReadAllBytes(); nextOffset = (uint)originalData.Length; Populate(reader); } } void Populate(IImageStream reader) { var chars = new char[0x200]; reader.Position = 1; while (reader.Position < reader.Length) { uint offset = (uint)reader.Position; uint len; if (!reader.ReadCompressedUInt32(out len)) { if (offset == reader.Position) reader.Position++; continue; } if (len == 0 || reader.Position + len > reader.Length) continue; int stringLen = (int)len / 2; if (stringLen > chars.Length) Array.Resize(ref chars, stringLen); for (int i = 0; i < stringLen; i++) chars[i] = (char)reader.ReadUInt16(); if ((len & 1) != 0) reader.ReadByte(); var s = new string(chars, 0, stringLen); if (!cachedDict.ContainsKey(s)) cachedDict[s] = offset; } } /// /// Adds a string to the #US heap /// /// The string /// The offset of the string in the #US heap public uint Add(string s) { if (isReadOnly) throw new ModuleWriterException("Trying to modify #US when it's read-only"); if (s == null) s = string.Empty; uint offset; if (cachedDict.TryGetValue(s, out offset)) return offset; return AddToCache(s); } /// /// Adds a string to the #US heap /// /// The string /// The offset of the string in the #US heap public uint Create(string s) { if (isReadOnly) throw new ModuleWriterException("Trying to modify #US when it's read-only"); return AddToCache(s ?? string.Empty); } uint AddToCache(string s) { uint offset; cached.Add(s); cachedDict[s] = offset = nextOffset; nextOffset += (uint)GetRawDataSize(s); if (offset > 0x00FFFFFF) throw new ModuleWriterException("#US heap is too big"); return offset; } /// public override uint GetRawLength() { return nextOffset; } /// protected override void WriteToImpl(BinaryWriter writer) { if (originalData != null) writer.Write(originalData); else writer.Write((byte)0); uint offset = originalData != null ? (uint)originalData.Length : 1; foreach (var s in cached) { int rawLen = GetRawDataSize(s); byte[] rawData; if (userRawData != null && userRawData.TryGetValue(offset, out rawData)) { if (rawData.Length != rawLen) throw new InvalidOperationException("Invalid length of raw data"); writer.Write(rawData); } else WriteString(writer, s); offset += (uint)rawLen; } } void WriteString(BinaryWriter writer, string s) { writer.WriteCompressedUInt32((uint)s.Length * 2 + 1); byte last = 0; for (int i = 0; i < s.Length; i++) { ushort c = (ushort)s[i]; writer.Write(c); if (c > 0xFF || (1 <= c && c <= 8) || (0x0E <= c && c <= 0x1F) || c == 0x27 || c == 0x2D || c == 0x7F) last = 1; } writer.Write(last); } /// public int GetRawDataSize(string data) { return Utils.GetCompressedUInt32Length((uint)data.Length * 2 + 1) + data.Length * 2 + 1; } /// public void SetRawData(uint offset, byte[] rawData) { if (rawData == null) throw new ArgumentNullException("rawData"); if (userRawData == null) userRawData = new Dictionary(); userRawData[offset] = rawData; } /// public IEnumerable> GetAllRawData() { var memStream = new MemoryStream(); var writer = new BinaryWriter(memStream); uint offset = originalData != null ? (uint)originalData.Length : 1; foreach (var s in cached) { memStream.Position = 0; memStream.SetLength(0); WriteString(writer, s); yield return new KeyValuePair(offset, memStream.ToArray()); offset += (uint)memStream.Length; } } } } dnlib-2.1_VS2010/src/DotNet/Writer/UniqueChunkList.cs000066400000000000000000000031611325033663500222500ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Re-uses existing chunks to save space /// /// Chunk type public sealed class UniqueChunkList : ChunkListBase where T : class, IChunk { Dictionary dict; /// /// Default constructor /// public UniqueChunkList() : this(EqualityComparer.Default) { } /// /// Constructor /// /// Compares the chunk type public UniqueChunkList(IEqualityComparer chunkComparer) { this.chunks = new List(); this.dict = new Dictionary(new ElemEqualityComparer(chunkComparer)); } /// public override void SetOffset(FileOffset offset, RVA rva) { dict = null; base.SetOffset(offset, rva); } /// /// Adds a if not already present /// /// The chunk to add or null if none /// Chunk alignment /// The original input if it wasn't present, or the cached one public T Add(T chunk, uint alignment) { if (setOffsetCalled) throw new InvalidOperationException("SetOffset() has already been called"); if (chunk == null) return null; var elem = new Elem(chunk, alignment); Elem other; if (dict.TryGetValue(elem, out other)) return other.chunk; dict[elem] = elem; chunks.Add(elem); return elem.chunk; } } } dnlib-2.1_VS2010/src/DotNet/Writer/Win32ResourcesChunk.cs000066400000000000000000000437351325033663500227560ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using System.Text; using dnlib.IO; using dnlib.PE; using dnlib.W32Resources; namespace dnlib.DotNet.Writer { /// /// Writes Win32 resources /// public sealed class Win32ResourcesChunk : IChunk { readonly Win32Resources win32Resources; FileOffset offset; RVA rva; uint length; readonly Dictionary dirDict = new Dictionary(); readonly List dirList = new List(); readonly Dictionary dataHeaderDict = new Dictionary(); readonly List dataHeaderList = new List(); readonly Dictionary stringsDict = new Dictionary(StringComparer.Ordinal); readonly List stringsList = new List(); readonly Dictionary dataDict = new Dictionary(); readonly List dataList = new List(); /// public FileOffset FileOffset { get { return offset; } } /// public RVA RVA { get { return rva; } } /// /// Constructor /// /// Win32 resources public Win32ResourcesChunk(Win32Resources win32Resources) { this.win32Resources = win32Resources; } /// /// Returns the and of a /// . must have been called. /// /// A /// Updated with the file offset /// Updated with the RVA /// true if is valid and /// and have been updated. false /// if is not part of the Win32 resources. public bool GetFileOffsetAndRvaOf(ResourceDirectoryEntry dirEntry, out FileOffset fileOffset, out RVA rva) { var dir = dirEntry as ResourceDirectory; if (dir != null) return GetFileOffsetAndRvaOf(dir, out fileOffset, out rva); var dataHeader = dirEntry as ResourceData; if (dataHeader != null) return GetFileOffsetAndRvaOf(dataHeader, out fileOffset, out rva); fileOffset = 0; rva = 0; return false; } /// /// Returns the of a . /// must have been called. /// /// A /// The file offset or 0 if is invalid public FileOffset GetFileOffset(ResourceDirectoryEntry dirEntry) { FileOffset fileOffset; RVA rva; GetFileOffsetAndRvaOf(dirEntry, out fileOffset, out rva); return fileOffset; } /// /// Returns the of a . /// must have been called. /// /// A /// The RVA or 0 if is invalid public RVA GetRVA(ResourceDirectoryEntry dirEntry) { FileOffset fileOffset; RVA rva; GetFileOffsetAndRvaOf(dirEntry, out fileOffset, out rva); return rva; } /// /// Returns the and of a /// . must have been called. /// /// A /// Updated with the file offset /// Updated with the RVA /// true if is valid and /// and have been updated. false /// if is not part of the Win32 resources. public bool GetFileOffsetAndRvaOf(ResourceDirectory dir, out FileOffset fileOffset, out RVA rva) { uint offs; if (dir == null || !dirDict.TryGetValue(dir, out offs)) { fileOffset = 0; rva = 0; return false; } fileOffset = offset + offs; rva = this.rva + offs; return true; } /// /// Returns the of a . /// must have been called. /// /// A /// The file offset or 0 if is invalid public FileOffset GetFileOffset(ResourceDirectory dir) { FileOffset fileOffset; RVA rva; GetFileOffsetAndRvaOf(dir, out fileOffset, out rva); return fileOffset; } /// /// Returns the of a . /// must have been called. /// /// A /// The RVA or 0 if is invalid public RVA GetRVA(ResourceDirectory dir) { FileOffset fileOffset; RVA rva; GetFileOffsetAndRvaOf(dir, out fileOffset, out rva); return rva; } /// /// Returns the and of a /// . must have been called. /// /// A /// Updated with the file offset /// Updated with the RVA /// true if is valid and /// and have been updated. false /// if is not part of the Win32 resources. public bool GetFileOffsetAndRvaOf(ResourceData dataHeader, out FileOffset fileOffset, out RVA rva) { uint offs; if (dataHeader == null || !dataHeaderDict.TryGetValue(dataHeader, out offs)) { fileOffset = 0; rva = 0; return false; } fileOffset = offset + offs; rva = this.rva + offs; return true; } /// /// Returns the of a . /// must have been called. /// /// A /// The file offset or 0 if is invalid public FileOffset GetFileOffset(ResourceData dataHeader) { FileOffset fileOffset; RVA rva; GetFileOffsetAndRvaOf(dataHeader, out fileOffset, out rva); return fileOffset; } /// /// Returns the of a . /// must have been called. /// /// A /// The RVA or 0 if is invalid public RVA GetRVA(ResourceData dataHeader) { FileOffset fileOffset; RVA rva; GetFileOffsetAndRvaOf(dataHeader, out fileOffset, out rva); return rva; } /// /// Returns the and of the raw data /// owned by a . must have been called. /// /// A 's /// Updated with the file offset /// Updated with the RVA /// true if is valid and /// and have been updated. false /// if is not part of the Win32 resources. public bool GetFileOffsetAndRvaOf(IBinaryReader data, out FileOffset fileOffset, out RVA rva) { uint offs; if (data == null || !dataDict.TryGetValue(data, out offs)) { fileOffset = 0; rva = 0; return false; } fileOffset = offset + offs; rva = this.rva + offs; return true; } /// /// Returns the of the raw data owned by a /// . must have been called. /// /// A 's /// The file offset or 0 if is invalid public FileOffset GetFileOffset(IBinaryReader data) { FileOffset fileOffset; RVA rva; GetFileOffsetAndRvaOf(data, out fileOffset, out rva); return fileOffset; } /// /// Returns the of the raw data owned by a . /// must have been called. /// /// A 's /// The RVA or 0 if is invalid public RVA GetRVA(IBinaryReader data) { FileOffset fileOffset; RVA rva; GetFileOffsetAndRvaOf(data, out fileOffset, out rva); return rva; } /// /// Returns the and of a /// 's name. must have been /// called. /// /// The name of a /// Updated with the file offset /// Updated with the RVA /// true if is valid and /// and have been updated. false /// if is not part of the Win32 resources. public bool GetFileOffsetAndRvaOf(string name, out FileOffset fileOffset, out RVA rva) { uint offs; if (name == null || !stringsDict.TryGetValue(name, out offs)) { fileOffset = 0; rva = 0; return false; } fileOffset = offset + offs; rva = this.rva + offs; return true; } /// /// Returns the of a 's name. /// must have been called. /// /// The name of a /// The file offset or 0 if is invalid public FileOffset GetFileOffset(string name) { FileOffset fileOffset; RVA rva; GetFileOffsetAndRvaOf(name, out fileOffset, out rva); return fileOffset; } /// /// Returns the of a 's name. /// must have been called. /// /// The name of a /// The RVA or 0 if is invalid public RVA GetRVA(string name) { FileOffset fileOffset; RVA rva; GetFileOffsetAndRvaOf(name, out fileOffset, out rva); return rva; } const uint RESOURCE_DIR_ALIGNMENT = 4; const uint RESOURCE_DATA_HEADER_ALIGNMENT = 4; const uint RESOURCE_STRING_ALIGNMENT = 2; const uint RESOURCE_DATA_ALIGNMENT = 4; /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; if (win32Resources == null) return; FindDirectoryEntries(); // Place everything in the following order: // 1. All resource directories. The root is always first. // 2. All resource data headers. // 3. All the strings. // 4. All resource data. uint rsrcOffset = 0; uint maxAlignment = 1; maxAlignment = Math.Max(maxAlignment, RESOURCE_DIR_ALIGNMENT); maxAlignment = Math.Max(maxAlignment, RESOURCE_DATA_HEADER_ALIGNMENT); maxAlignment = Math.Max(maxAlignment, RESOURCE_STRING_ALIGNMENT); maxAlignment = Math.Max(maxAlignment, RESOURCE_DATA_ALIGNMENT); if (((uint)offset & (maxAlignment - 1)) != 0) throw new ModuleWriterException(string.Format("Win32 resources section isn't {0}-byte aligned", maxAlignment)); if (maxAlignment > ModuleWriterBase.DEFAULT_WIN32_RESOURCES_ALIGNMENT) throw new ModuleWriterException("maxAlignment > DEFAULT_WIN32_RESOURCES_ALIGNMENT"); foreach (var dir in dirList) { rsrcOffset = Utils.AlignUp(rsrcOffset, RESOURCE_DIR_ALIGNMENT); dirDict[dir] = rsrcOffset; if (dir != dirList[0]) AddString(dir.Name); rsrcOffset += 16 + (uint)(dir.Directories.Count + dir.Data.Count) * 8; } foreach (var data in dataHeaderList) { rsrcOffset = Utils.AlignUp(rsrcOffset, RESOURCE_DATA_HEADER_ALIGNMENT); dataHeaderDict[data] = rsrcOffset; AddString(data.Name); AddData(data.Data); rsrcOffset += 16; } foreach (var s in stringsList) { rsrcOffset = Utils.AlignUp(rsrcOffset, RESOURCE_STRING_ALIGNMENT); stringsDict[s] = rsrcOffset; rsrcOffset += 2 + (uint)(s.Length * 2); } foreach (var data in dataList) { rsrcOffset = Utils.AlignUp(rsrcOffset, RESOURCE_DATA_ALIGNMENT); dataDict[data] = rsrcOffset; rsrcOffset += (uint)data.Length; } length = rsrcOffset; } void AddData(IBinaryReader data) { if (dataDict.ContainsKey(data)) return; dataList.Add(data); dataDict.Add(data, 0); } void AddString(ResourceName name) { if (!name.HasName || stringsDict.ContainsKey(name.Name)) return; stringsList.Add(name.Name); stringsDict.Add(name.Name, 0); } void FindDirectoryEntries() { FindDirectoryEntries(win32Resources.Root); } void FindDirectoryEntries(ResourceDirectory dir) { if (dirDict.ContainsKey(dir)) return; dirList.Add(dir); dirDict[dir] = 0; foreach (var dir2 in dir.Directories) FindDirectoryEntries(dir2); foreach (var data in dir.Data) { if (dataHeaderDict.ContainsKey(data)) continue; dataHeaderList.Add(data); dataHeaderDict[data] = 0; } } /// public uint GetFileLength() { return Utils.AlignUp(length, ModuleWriterBase.DEFAULT_WIN32_RESOURCES_ALIGNMENT); } /// public uint GetVirtualSize() { return GetFileLength(); } /// public void WriteTo(BinaryWriter writer) { uint offset = 0; // The order here must be the same as in SetOffset() foreach (var dir in dirList) { uint padding = Utils.AlignUp(offset, RESOURCE_DIR_ALIGNMENT) - offset; writer.WriteZeros((int)padding); offset += padding; if (dirDict[dir] != offset) throw new ModuleWriterException("Invalid Win32 resource directory offset"); offset += WriteTo(writer, dir); } foreach (var dataHeader in dataHeaderList) { uint padding = Utils.AlignUp(offset, RESOURCE_DATA_HEADER_ALIGNMENT) - offset; writer.WriteZeros((int)padding); offset += padding; if (dataHeaderDict[dataHeader] != offset) throw new ModuleWriterException("Invalid Win32 resource data header offset"); offset += WriteTo(writer, dataHeader); } foreach (var s in stringsList) { uint padding = Utils.AlignUp(offset, RESOURCE_STRING_ALIGNMENT) - offset; writer.WriteZeros((int)padding); offset += padding; if (stringsDict[s] != offset) throw new ModuleWriterException("Invalid Win32 resource string offset"); var bytes = Encoding.Unicode.GetBytes(s); if (bytes.Length / 2 > ushort.MaxValue) throw new ModuleWriterException("Win32 resource entry name is too long"); writer.Write((ushort)(bytes.Length / 2)); writer.Write(bytes); offset += 2 + (uint)bytes.Length; } byte[] dataBuffer = new byte[0x2000]; foreach (var data in dataList) { uint padding = Utils.AlignUp(offset, RESOURCE_DATA_ALIGNMENT) - offset; writer.WriteZeros((int)padding); offset += padding; if (dataDict[data] != offset) throw new ModuleWriterException("Invalid Win32 resource data offset"); data.Position = 0; offset += data.WriteTo(writer, dataBuffer); } writer.WriteZeros((int)(Utils.AlignUp(length, ModuleWriterBase.DEFAULT_WIN32_RESOURCES_ALIGNMENT) - length)); } uint WriteTo(BinaryWriter writer, ResourceDirectory dir) { writer.Write(dir.Characteristics); writer.Write(dir.TimeDateStamp); writer.Write(dir.MajorVersion); writer.Write(dir.MinorVersion); List named; List ids; GetNamedAndIds(dir, out named, out ids); if (named.Count > ushort.MaxValue || ids.Count > ushort.MaxValue) throw new ModuleWriterException("Too many named/id Win32 resource entries"); writer.Write((ushort)named.Count); writer.Write((ushort)ids.Count); // These must be sorted in ascending order. Names are case insensitive. named.Sort((a, b) => a.Name.Name.ToUpperInvariant().CompareTo(b.Name.Name.ToUpperInvariant())); ids.Sort((a, b) => a.Name.Id.CompareTo(b.Name.Id)); foreach (var d in named) { writer.Write(0x80000000 | stringsDict[d.Name.Name]); writer.Write(GetDirectoryEntryOffset(d)); } foreach (var d in ids) { writer.Write(d.Name.Id); writer.Write(GetDirectoryEntryOffset(d)); } return 16 + (uint)(named.Count + ids.Count) * 8; } uint GetDirectoryEntryOffset(ResourceDirectoryEntry e) { if (e is ResourceData) return dataHeaderDict[(ResourceData)e]; return 0x80000000 | dirDict[(ResourceDirectory)e]; } static void GetNamedAndIds(ResourceDirectory dir, out List named, out List ids) { named = new List(); ids = new List(); foreach (var d in dir.Directories) { if (d.Name.HasId) ids.Add(d); else named.Add(d); } foreach (var d in dir.Data) { if (d.Name.HasId) ids.Add(d); else named.Add(d); } } uint WriteTo(BinaryWriter writer, ResourceData dataHeader) { writer.Write((uint)rva + dataDict[dataHeader.Data]); writer.Write((uint)dataHeader.Data.Length); writer.Write(dataHeader.CodePage); writer.Write(dataHeader.Reserved); return 16; } } } dnlib-2.1_VS2010/src/DotNet/Writer/WriterUtils.cs000066400000000000000000000021501325033663500214470ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; namespace dnlib.DotNet.Writer { static class WriterUtils { public static uint WriteCompressedUInt32(this BinaryWriter writer, IWriterError helper, uint value) { if (value > 0x1FFFFFFF) { helper.Error("UInt32 value is too big and can't be compressed"); value = 0x1FFFFFFF; } writer.WriteCompressedUInt32(value); return value; } public static int WriteCompressedInt32(this BinaryWriter writer, IWriterError helper, int value) { if (value < -0x10000000) { helper.Error("Int32 value is too small and can't be compressed."); value = -0x10000000; } else if (value > 0x0FFFFFFF) { helper.Error("Int32 value is too big and can't be compressed."); value = 0x0FFFFFFF; } writer.WriteCompressedInt32(value); return value; } public static void Write(this BinaryWriter writer, IWriterError helper, UTF8String s) { if (UTF8String.IsNull(s)) { helper.Error("UTF8String is null"); s = UTF8String.Empty; } writer.WriteCompressedUInt32(helper, (uint)s.DataLength); writer.Write(s.Data); } } } dnlib-2.1_VS2010/src/ExtensionAttribute.cs000066400000000000000000000004411325033663500203420ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info #pragma warning disable 1591 // XML doc warning namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] public sealed class ExtensionAttribute : Attribute { } } dnlib-2.1_VS2010/src/HandleProcessCorruptedStateExceptionsAttribute.cs000066400000000000000000000004571325033663500260620ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info #pragma warning disable 1591 // XML doc warning namespace System.Runtime.ExceptionServices { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] sealed class HandleProcessCorruptedStateExceptionsAttribute : Attribute { } } dnlib-2.1_VS2010/src/IO/000077500000000000000000000000001325033663500144635ustar00rootroot00000000000000dnlib-2.1_VS2010/src/IO/BinaryReaderStream.cs000066400000000000000000000046711325033663500205450ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; namespace dnlib.IO { /// /// A class that can be used when you have a /// but must use a /// sealed class BinaryReaderStream : Stream { IBinaryReader reader; readonly bool ownsReader; /// /// Constructor /// /// Reader. This instance does NOT own this reader. public BinaryReaderStream(IBinaryReader reader) : this(reader, false) { } /// /// Constructor /// /// Reader /// true if this instance owns public BinaryReaderStream(IBinaryReader reader, bool ownsReader) { this.reader = reader; this.ownsReader = ownsReader; } /// public override bool CanRead { get { return true; } } /// public override bool CanSeek { get { return true; } } /// public override bool CanWrite { get { return false; } } /// public override void Flush() { } /// public override long Length { get { return reader.Length; } } /// public override long Position { get { return reader.Position; } set { reader.Position = value; } } /// public override int Read(byte[] buffer, int offset, int count) { return reader.Read(buffer, offset, count); } /// public override int ReadByte() { try { return reader.ReadByte(); } catch (IOException) { return -1; } } /// public override long Seek(long offset, SeekOrigin origin) { switch (origin) { case SeekOrigin.Begin: Position = offset; break; case SeekOrigin.Current:Position += offset; break; case SeekOrigin.End: Position = Length + offset; break; } return Position; } /// public override void SetLength(long value) { throw new NotImplementedException(); } /// public override void Write(byte[] buffer, int offset, int count) { throw new NotImplementedException(); } /// protected override void Dispose(bool disposing) { if (disposing) { var r = reader; if (ownsReader && r != null) r.Dispose(); reader = null; } base.Dispose(disposing); } } } dnlib-2.1_VS2010/src/IO/FileOffset.cs000066400000000000000000000014161325033663500170420ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.IO { /// /// Represents a file offset /// public enum FileOffset : long { } partial class IOExtensions { /// /// Align up /// /// this /// Alignment public static FileOffset AlignUp(this FileOffset offset, uint alignment) { return (FileOffset)(((uint)offset + alignment - 1) & ~(alignment - 1)); } /// /// Align up /// /// this /// Alignment public static FileOffset AlignUp(this FileOffset offset, int alignment) { return (FileOffset)(((uint)offset + alignment - 1) & ~(alignment - 1)); } } } dnlib-2.1_VS2010/src/IO/FileSection.cs000066400000000000000000000023711325033663500172210ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Diagnostics; namespace dnlib.IO { /// /// Base class for classes needing to implement IFileSection /// [DebuggerDisplay("O:{startOffset} L:{size} {GetType().Name}")] public class FileSection : IFileSection { /// /// The start file offset of this section /// protected FileOffset startOffset; /// /// Size of the section /// protected uint size; /// public FileOffset StartOffset { get { return startOffset; } } /// public FileOffset EndOffset { get { return startOffset + size; } } /// /// Set to 's current position /// /// The reader protected void SetStartOffset(IImageStream reader) { startOffset = (FileOffset)reader.Position; } /// /// Set according to 's current position /// /// The reader protected void SetEndoffset(IImageStream reader) { size = (uint)(reader.Position - startOffset); startOffset = reader.FileOffset + (long)startOffset; } } } dnlib-2.1_VS2010/src/IO/IBinaryReader.cs000066400000000000000000000547641325033663500175120ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using System.Text; namespace dnlib.IO { /// /// Reads binary data /// public interface IBinaryReader : IDisposable { /// /// Returns the length of the stream /// long Length { get; } /// /// Gets/sets the position /// long Position { get; set; } /// /// Reads bytes from the current /// and increments by bytes /// /// Number of bytes to read /// All available bytes. This can be less than bytes /// if there's not enough bytes left. /// An I/O error occurs byte[] ReadBytes(int size); /// /// Reads bytes to and increments /// by the number of bytes read. /// /// Buffer /// Offset in buffer where to place all read bytes /// Number of bytes to read /// Number of bytes read, and can be less than if /// there's no more bytes to read. int Read(byte[] buffer, int offset, int length); /// /// Reads bytes until byte is found. is /// incremented by the number of bytes read (size of return value). /// /// The terminating byte /// All the bytes (not including ) or null if /// wasn't found. byte[] ReadBytesUntilByte(byte b); /// /// Reads a from the current position and increments by 1 /// /// The 8-bit signed byte /// An I/O error occurs sbyte ReadSByte(); /// /// Reads a from the current position and increments by 1 /// /// The 8-bit unsigned byte /// An I/O error occurs byte ReadByte(); /// /// Reads a from the current position and increments by 2 /// /// The 16-bit signed integer /// An I/O error occurs short ReadInt16(); /// /// Reads a from the current position and increments by 2 /// /// The 16-bit unsigned integer /// An I/O error occurs ushort ReadUInt16(); /// /// Reads a from the current position and increments by 4 /// /// The 32-bit signed integer /// An I/O error occurs int ReadInt32(); /// /// Reads a from the current position and increments by 4 /// /// The 32-bit unsigned integer /// An I/O error occurs uint ReadUInt32(); /// /// Reads a from the current position and increments by 8 /// /// The 64-bit signed integer /// An I/O error occurs long ReadInt64(); /// /// Reads a from the current position and increments by 8 /// /// The 64-bit unsigned integer /// An I/O error occurs ulong ReadUInt64(); /// /// Reads a from the current position and increments by 4 /// /// The 32-bit single /// An I/O error occurs float ReadSingle(); /// /// Reads a from the current position and increments by 8 /// /// The 64-bit double /// An I/O error occurs double ReadDouble(); /// /// Reads a from the current position and increments /// by the number of bytes read. /// /// Number of characters to read /// The string /// An I/O error occurs string ReadString(int chars); } public static partial class IOExtensions { /// /// Reads a at offset /// /// this /// Offset /// The public static bool ReadBooleanAt(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadBoolean(); } /// /// Reads a at offset /// /// this /// Offset /// The public static byte ReadByteAt(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadByte(); } /// /// Reads a at offset /// /// this /// Offset /// The public static sbyte ReadSByteAt(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadSByte(); } /// /// Reads a at offset /// /// this /// Offset /// The public static short ReadInt16At(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadInt16(); } /// /// Reads a at offset /// /// this /// Offset /// The public static ushort ReadUInt16At(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadUInt16(); } /// /// Reads a at offset /// /// this /// Offset /// The public static int ReadInt32At(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadInt32(); } /// /// Reads a at offset /// /// this /// Offset /// The public static uint ReadUInt32At(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadUInt32(); } /// /// Reads a at offset /// /// this /// Offset /// The public static long ReadInt64At(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadInt64(); } /// /// Reads a at offset /// /// this /// Offset /// The public static ulong ReadUInt64At(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadUInt64(); } /// /// Reads a at offset /// /// this /// Offset /// The public static float ReadSingleAt(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadSingle(); } /// /// Reads a at offset /// /// this /// Offset /// The public static double ReadDoubleAt(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadDouble(); } /// /// Reads a at offset /// /// this /// Offset /// The public static string ReadStringAt(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadString(); } /// /// Reads a at offset /// /// this /// Offset /// Encoding /// The public static string ReadStringAt(this IBinaryReader reader, long offset, Encoding encoding) { reader.Position = offset; return reader.ReadString(encoding); } /// /// Reads a at offset /// /// this /// Offset /// The public static char ReadCharAt(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadChar(); } /// /// Reads a at offset /// /// this /// Offset /// Encoding /// The public static char ReadCharAt(this IBinaryReader reader, long offset, Encoding encoding) { reader.Position = offset; return reader.ReadChar(encoding); } /// /// Reads a at offset /// /// this /// Offset /// The public static decimal ReadDecimalAt(this IBinaryReader reader, long offset) { reader.Position = offset; return reader.ReadDecimal(); } /// /// Reads all remaining bytes /// /// this /// All remaining bytes public static byte[] ReadRemainingBytes(this IBinaryReader reader) { if (reader.Position >= reader.Length) return new byte[0]; return reader.ReadBytes((int)(reader.Length - reader.Position)); } /// /// Reads all bytes /// /// this /// All bytes public static byte[] ReadAllBytes(this IBinaryReader reader) { reader.Position = 0; return reader.ReadBytes((int)reader.Length); } /// /// Reads a from the current position and increments by 1 /// /// this /// The boolean /// An I/O error occurs public static bool ReadBoolean(this IBinaryReader self) { return self.ReadByte() != 0; } /// /// Reads a from the current position and increments by 2 /// /// this /// The char /// An I/O error occurs public static char ReadChar(this IBinaryReader self) { return self.ReadChar(Encoding.UTF8); } /// /// Reads a from the current position and increments by 2 /// /// this /// Encoding /// The char /// An I/O error occurs public static char ReadChar(this IBinaryReader self, Encoding encoding) { // This is slow but this method should rarely be called... var decoder = encoding.GetDecoder(); bool twoBytes = encoding is UnicodeEncoding; byte[] bytes = new byte[2]; char[] chars = new char[1]; while (true) { bytes[0] = self.ReadByte(); if (twoBytes) bytes[1] = self.ReadByte(); int x = decoder.GetChars(bytes, 0, twoBytes ? 2 : 1, chars, 0); if (x != 0) break; } return chars[0]; } /// /// Reads a UTF-8 from the current position and increments /// by the length of the string. /// /// this /// The string public static string ReadString(this IBinaryReader reader) { return reader.ReadString(Encoding.UTF8); } /// /// Reads a from the current position and increments /// by the length of the string. /// /// this /// Encoding /// The string public static string ReadString(this IBinaryReader reader, Encoding encoding) { int len = reader.Read7BitEncodedInt32(); return encoding.GetString(reader.ReadBytes(len)); } /// /// Reads a from the current position and increments /// by 16 /// /// this /// The decmial /// An I/O error occurs public static decimal ReadDecimal(this IBinaryReader reader) { var bits = new int[4] { reader.ReadInt32(), // lo reader.ReadInt32(), // mid reader.ReadInt32(), // hi reader.ReadInt32(), // flags }; return new decimal(bits); } /// /// Reads chars /// /// this /// Number of s to read /// All the chars public static char[] ReadChars(this IBinaryReader reader, int length) { var chars = new char[length]; for (int i = 0; i < length; i++) chars[i] = reader.ReadChar(); return chars; } /// /// Reads a compressed from the current position in /// /// Max value it can return is 0x1FFFFFFF /// The reader /// Decompressed value /// true if successful, false on failure public static bool ReadCompressedUInt32(this IBinaryReader reader, out uint val) { var pos = reader.Position; var len = reader.Length; if (pos >= len) { val = 0; return false; } byte b = reader.ReadByte(); if ((b & 0x80) == 0) { val = b; return true; } if ((b & 0xC0) == 0x80) { if (pos + 1 < pos || pos + 1 >= len) { val = 0; return false; } val = (uint)(((b & 0x3F) << 8) | reader.ReadByte()); return true; } // The encoding 111x isn't allowed but the CLR sometimes doesn't verify this // and just assumes it's 110x. Don't fail if it's 111x, just assume it's 110x. if (pos + 3 < pos || pos + 3 >= len) { val = 0; return false; } val = (uint)(((b & 0x1F) << 24) | (reader.ReadByte() << 16) | (reader.ReadByte() << 8) | reader.ReadByte()); return true; } /// /// Reads a compressed from the current position in /// /// The reader /// Decompressed value /// true if successful, false on failure public static bool ReadCompressedInt32(this IBinaryReader reader, out int val) { var pos = reader.Position; var len = reader.Length; if (pos >= len) { val = 0; return false; } byte b = reader.ReadByte(); if ((b & 0x80) == 0) { if ((b & 1) != 0) val = -0x40 | (b >> 1); else val = (b >> 1); return true; } if ((b & 0xC0) == 0x80) { if (pos + 1 < pos || pos + 1 >= len) { val = 0; return false; } uint tmp = (uint)(((b & 0x3F) << 8) | reader.ReadByte()); if ((tmp & 1) != 0) val = -0x2000 | (int)(tmp >> 1); else val = (int)(tmp >> 1); return true; } if ((b & 0xE0) == 0xC0) { if (pos + 3 < pos || pos + 3 >= len) { val = 0; return false; } uint tmp = (uint)(((b & 0x1F) << 24) | (reader.ReadByte() << 16) | (reader.ReadByte() << 8) | reader.ReadByte()); if ((tmp & 1) != 0) val = -0x10000000 | (int)(tmp >> 1); else val = (int)(tmp >> 1); return true; } val = 0; return false; } /// /// Reads a compressed from the current position in /// /// The reader /// The value public static uint ReadCompressedUInt32(this IBinaryReader reader) { uint val; if (!reader.ReadCompressedUInt32(out val)) throw new IOException("Could not read a compressed UInt32"); return val; } /// /// Reads a compressed from the current position in /// /// The reader /// The value public static int ReadCompressedInt32(this IBinaryReader reader) { int val; if (!reader.ReadCompressedInt32(out val)) throw new IOException("Could not read a compressed Int32"); return val; } /// /// Reads a 7-bit encoded integer /// /// this /// The decoded integer public static uint Read7BitEncodedUInt32(this IBinaryReader reader) { uint val = 0; int bits = 0; for (int i = 0; i < 5; i++) { byte b = reader.ReadByte(); val |= (uint)(b & 0x7F) << bits; if ((b & 0x80) == 0) return val; bits += 7; } throw new IOException("Invalid encoded UInt32"); } /// /// Reads a 7-bit encoded integer /// /// this /// The decoded integer public static int Read7BitEncodedInt32(this IBinaryReader reader) { return (int)reader.Read7BitEncodedUInt32(); } /// /// Creates a using . The created /// doesn't own , so it's not /// 'd. /// /// this /// A new instance public static Stream CreateStream(this IBinaryReader reader) { return new BinaryReaderStream(reader); } /// /// Creates a using /// /// this /// true if the created owns /// /// A new instance public static Stream CreateStream(this IBinaryReader reader, bool ownsReader) { return new BinaryReaderStream(reader, ownsReader); } /// /// Checks whether we can read bytes /// /// Reader /// Size in bytes public static bool CanRead(this IBinaryReader reader, int size) { return (reader.Position + size <= reader.Length && reader.Position + size >= reader.Position) || size == 0; } /// /// Checks whether we can read bytes /// /// Reader /// Size in bytes public static bool CanRead(this IBinaryReader reader, uint size) { return (reader.Position + size <= reader.Length && reader.Position + size >= reader.Position) || size == 0; } /// /// Writes , starting at 's current /// position, to starting at 's /// current position. Returns the number of bytes written. /// /// Reader /// Writer /// Number of bytes written /// Could not write all bytes or data is too big public static uint WriteTo(this IBinaryReader reader, BinaryWriter writer) { if (reader.Position >= reader.Length) return 0; return reader.WriteTo(writer, new byte[0x2000]); } /// /// Writes , starting at 's current /// position, to starting at 's /// current position. Returns the number of bytes written. /// /// Reader /// Writer /// Temp buffer during writing /// Number of bytes written /// Could not write all bytes or data is too big public static uint WriteTo(this IBinaryReader reader, BinaryWriter writer, byte[] dataBuffer) { if (reader.Position >= reader.Length) return 0; long longLenLeft = reader.Length - reader.Position; if (longLenLeft > uint.MaxValue) throw new IOException("Data is too big"); uint lenLeft = (uint)longLenLeft; uint writtenBytes = lenLeft; while (lenLeft > 0) { int num = (int)Math.Min((uint)dataBuffer.Length, lenLeft); lenLeft -= (uint)num; if (num != reader.Read(dataBuffer, 0, num)) throw new IOException("Could not read all reader bytes"); writer.Write(dataBuffer, 0, num); } return writtenBytes; } } } dnlib-2.1_VS2010/src/IO/IFileSection.cs000066400000000000000000000007121325033663500173270ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.IO { /// /// Represents a section in a file /// public interface IFileSection { /// /// Start offset of the section in the file /// FileOffset StartOffset { get; } /// /// End offset of the section in the file. This is one byte after the last /// valid offset in the section. /// FileOffset EndOffset { get; } } } dnlib-2.1_VS2010/src/IO/IImageStream.cs000066400000000000000000000025161325033663500173250ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.IO { /// /// Interface to access part of some data /// public interface IImageStream : IBinaryReader { /// /// Returns the file offset of the stream /// FileOffset FileOffset { get; } /// /// Creates a sub stream that can access parts of this stream /// /// File offset relative to the start of this stream /// Length /// A new stream IImageStream Create(FileOffset offset, long length); } static partial class IOExtensions { /// /// Creates a stream that can access all data starting from /// /// this /// Offset relative to the beginning of the stream /// A new stream public static IImageStream Create(this IImageStream self, FileOffset offset) { return self.Create(offset, long.MaxValue); } /// /// Clones this /// /// this /// A new instance public static IImageStream Clone(this IImageStream self) { return self.Create(0, long.MaxValue); } } } dnlib-2.1_VS2010/src/IO/IImageStreamCreator.cs000066400000000000000000000025501325033663500206430ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.IO { /// /// Creates a new stream that accesses part of some data /// public interface IImageStreamCreator : IDisposable { /// /// The file name or null if data is not from a file /// string FileName { get; } /// /// Returns the total length of the original data /// long Length { get; } /// /// Creates a stream that can access only part of the data /// /// Offset within the original data /// Length of section within the original data /// A new stream IImageStream Create(FileOffset offset, long length); /// /// Creates a stream that can access all data /// /// A new stream IImageStream CreateFull(); } static partial class IOExtensions { /// /// Creates a stream that can access all data starting from /// /// this /// Offset within the original data /// A new stream public static IImageStream Create(this IImageStreamCreator self, FileOffset offset) { return self.Create(offset, long.MaxValue); } } } dnlib-2.1_VS2010/src/IO/IOExtensions.cs000066400000000000000000000002501325033663500173760ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.IO { /// /// Extension methods /// public static partial class IOExtensions { } } dnlib-2.1_VS2010/src/IO/ImageStreamCreator.cs000066400000000000000000000060161325033663500205330ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; namespace dnlib.IO { /// /// Creates a instance /// public static class ImageStreamCreator { static readonly bool isUnix; static ImageStreamCreator() { // See http://mono-project.com/FAQ:_Technical#Mono_Platforms for platform detection. int p = (int)Environment.OSVersion.Platform; if (p == 4 || p == 6 || p == 128) isUnix = true; } /// /// Creates a . It will be a /// if the operating system supports the memory /// mapped file methods we use, else . /// /// Filename /// A new instance public static IImageStreamCreator Create(string fileName) { return Create(fileName, false); } /// /// Creates a . It will be a /// if the operating system supports the memory /// mapped file methods we use, else . /// /// Filename /// true if we should map it as an executable. Not supported /// on Linux/Mac /// A new instance public static IImageStreamCreator Create(string fileName, bool mapAsImage) { var creator = CreateMemoryMappedFileStreamCreator(fileName, mapAsImage); if (creator != null) return creator; return new MemoryStreamCreator(File.ReadAllBytes(fileName)) { FileName = fileName }; } static MemoryMappedFileStreamCreator CreateMemoryMappedFileStreamCreator(string fileName, bool mapAsImage) { if (!isUnix) return MemoryMappedFileStreamCreator.CreateWindows(fileName, mapAsImage); else return MemoryMappedFileStreamCreator.CreateUnix(fileName, mapAsImage); } /// /// Creates a /// /// Filename /// A new instance public static IImageStream CreateImageStream(string fileName) { return CreateImageStream(fileName, false); } /// /// Creates a /// /// Filename /// true if we should map it as an executable. Not supported /// on Linux/Mac /// A new instance public static IImageStream CreateImageStream(string fileName, bool mapAsImage) { var creator = CreateMemoryMappedFileStreamCreator(fileName, mapAsImage); try { if (creator != null) return new UnmanagedMemoryImageStream(creator); return MemoryImageStream.Create(File.ReadAllBytes(fileName)); } catch { if (creator != null) creator.Dispose(); throw; } } } } dnlib-2.1_VS2010/src/IO/MemoryImageStream.cs000066400000000000000000000160511325033663500204040ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.IO; namespace dnlib.IO { /// /// IImageStream for byte[] /// [DebuggerDisplay("FO:{fileOffset} S:{Length}")] public sealed class MemoryImageStream : IImageStream { FileOffset fileOffset; byte[] data; int dataOffset; int dataEnd; int position; /// /// Creates a new instance /// /// Data /// A new instance public static MemoryImageStream Create(byte[] data) { return new MemoryImageStream(0, data, 0, data.Length); } /// /// Creates a new instance /// /// Data /// Start offset in /// Length of data /// A new instance public static MemoryImageStream Create(byte[] data, int offset, int len) { return new MemoryImageStream(0, data, offset, len); } /// /// Constructor /// /// File offset of data /// The data /// Start offset in /// Length of data public MemoryImageStream(FileOffset fileOffset, byte[] data, int dataOffset, int dataLength) { this.fileOffset = fileOffset; this.data = data; this.dataOffset = dataOffset; this.dataEnd = dataOffset + dataLength; this.position = dataOffset; } /// /// Gets the data /// internal byte[] DataArray { get { return data; } } /// /// Gets the start of the data in used by this stream /// internal int DataOffset { get { return dataOffset; } } /// public FileOffset FileOffset { get { return fileOffset; } } /// public long Length { get { return dataEnd - dataOffset; } } /// public long Position { get { return position - dataOffset; } set { long newPos = dataOffset + value; if (newPos < dataOffset || newPos > int.MaxValue) newPos = int.MaxValue; position = (int)newPos; } } /// /// Creates an empty instance /// public static MemoryImageStream CreateEmpty() { return new MemoryImageStream(0, new byte[0], 0, 0); } /// public IImageStream Create(FileOffset offset, long length) { if ((long)offset < 0 || length < 0) return MemoryImageStream.CreateEmpty(); int offs = (int)Math.Min((long)Length, (long)offset); int len = (int)Math.Min((long)Length - offs, length); return new MemoryImageStream((FileOffset)((long)fileOffset + (long)offset), data, dataOffset + offs, len); } /// public byte[] ReadBytes(int size) { if (size < 0) throw new IOException("Invalid size"); size = Math.Min(size, (int)Length - Math.Min((int)Length, (int)Position)); var newData = new byte[size]; Array.Copy(data, position, newData, 0, size); position += size; return newData; } /// public int Read(byte[] buffer, int offset, int length) { if (length < 0) throw new IOException("Invalid size"); length = Math.Min(length, (int)Length - Math.Min((int)Length, (int)Position)); Array.Copy(data, position, buffer, offset, length); position += length; return length; } /// public byte[] ReadBytesUntilByte(byte b) { int pos = GetPositionOf(b); if (pos < 0) return null; return ReadBytes(pos - position); } int GetPositionOf(byte b) { int pos = position; while (pos < dataEnd) { if (data[pos] == b) return pos; pos++; } return -1; } /// public sbyte ReadSByte() { if (position >= dataEnd) throw new IOException("Can't read one SByte"); return (sbyte)data[position++]; } /// public byte ReadByte() { if (position >= dataEnd) throw new IOException("Can't read one Byte"); return data[position++]; } /// public short ReadInt16() { if (position + 1 >= dataEnd) throw new IOException("Can't read one Int16"); return (short)(data[position++] | (data[position++] << 8)); } /// public ushort ReadUInt16() { if (position + 1 >= dataEnd) throw new IOException("Can't read one UInt16"); return (ushort)(data[position++] | (data[position++] << 8)); } /// public int ReadInt32() { if (position + 3 >= dataEnd) throw new IOException("Can't read one Int32"); return data[position++] | (data[position++] << 8) | (data[position++] << 16) | (data[position++] << 24); } /// public uint ReadUInt32() { if (position + 3 >= dataEnd) throw new IOException("Can't read one UInt32"); return (uint)(data[position++] | (data[position++] << 8) | (data[position++] << 16) | (data[position++] << 24)); } /// public long ReadInt64() { if (position + 7 >= dataEnd) throw new IOException("Can't read one Int64"); return (long)data[position++] | ((long)data[position++] << 8) | ((long)data[position++] << 16) | ((long)data[position++] << 24) | ((long)data[position++] << 32) | ((long)data[position++] << 40) | ((long)data[position++] << 48) | ((long)data[position++] << 56); } /// public ulong ReadUInt64() { if (position + 7 >= dataEnd) throw new IOException("Can't read one UInt64"); return (ulong)data[position++] | ((ulong)data[position++] << 8) | ((ulong)data[position++] << 16) | ((ulong)data[position++] << 24) | ((ulong)data[position++] << 32) | ((ulong)data[position++] << 40) | ((ulong)data[position++] << 48) | ((ulong)data[position++] << 56); } /// public float ReadSingle() { if (position + 3 >= dataEnd) throw new IOException("Can't read one Single"); var val = BitConverter.ToSingle(data, position); position += 4; return val; } /// public double ReadDouble() { if (position + 7 >= dataEnd) throw new IOException("Can't read one Double"); var val = BitConverter.ToDouble(data, position); position += 8; return val; } /// public unsafe string ReadString(int chars) { if ((uint)chars > (uint)int.MaxValue) throw new IOException("Not enough space to read the string"); if (position + chars * 2 < position || (chars != 0 && position + chars * 2 - 1 >= dataEnd)) throw new IOException("Not enough space to read the string"); string res; fixed (byte* p = data) res = new string((char*)(p + position), 0, chars); position += chars * 2; return res; } /// public void Dispose() { fileOffset = 0; data = null; dataOffset = 0; dataEnd = 0; position = 0; } } } dnlib-2.1_VS2010/src/IO/MemoryMappedFileStreamCreator.cs000066400000000000000000000274111325033663500227120ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Threading; using Microsoft.Win32.SafeHandles; namespace dnlib.IO { /// /// Maps a file into memory using MapViewOfFile() and creates streams /// that can access part of it in memory. /// /// Since this class maps a file into memory, the user should call /// to free any resources /// used by the class when it's no longer needed. [DebuggerDisplay("mmap: A:{data} L:{dataLength} {theFileName}")] sealed class MemoryMappedFileStreamCreator : UnmanagedMemoryStreamCreator { OSType osType = OSType.Unknown; long origDataLength; enum OSType : byte { Unknown, Windows, Unix, } [Serializable] sealed class MemoryMappedIONotSupportedException : IOException { public MemoryMappedIONotSupportedException() { } public MemoryMappedIONotSupportedException(string s) : base(s) { } public MemoryMappedIONotSupportedException(SerializationInfo info, StreamingContext context) : base(info, context) { } } static class Windows { const uint GENERIC_READ = 0x80000000; const uint FILE_SHARE_READ = 0x00000001; const uint OPEN_EXISTING = 3; const uint FILE_ATTRIBUTE_NORMAL = 0x00000080; const uint PAGE_READONLY = 0x02; const uint SEC_IMAGE = 0x1000000; const uint SECTION_MAP_READ = 0x0004; const uint FILE_MAP_READ = SECTION_MAP_READ; [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)] static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] static extern SafeFileHandle CreateFileMapping(SafeFileHandle hFile, IntPtr lpAttributes, uint flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName); [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] static extern IntPtr MapViewOfFile(SafeFileHandle hFileMappingObject, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, UIntPtr dwNumberOfBytesToMap); [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool UnmapViewOfFile(IntPtr lpBaseAddress); [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] static extern uint GetFileSize(SafeFileHandle hFile, out uint lpFileSizeHigh); const uint INVALID_FILE_SIZE = 0xFFFFFFFF; const int NO_ERROR = 0; public static void Mmap(MemoryMappedFileStreamCreator creator, bool mapAsImage) { using (var fileHandle = CreateFile(creator.theFileName, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero)) { if (fileHandle.IsInvalid) throw new IOException(string.Format("Could not open file {0} for reading. Error: {1:X8}", creator.theFileName, Marshal.GetLastWin32Error())); uint sizeHi; uint sizeLo = GetFileSize(fileHandle, out sizeHi); int hr; if (sizeLo == INVALID_FILE_SIZE && (hr = Marshal.GetLastWin32Error()) != NO_ERROR) throw new IOException(string.Format("Could not get file size. File: {0}, error: {1:X8}", creator.theFileName, hr)); var fileSize = ((long)sizeHi << 32) | sizeLo; using (var fileMapping = CreateFileMapping(fileHandle, IntPtr.Zero, PAGE_READONLY | (mapAsImage ? SEC_IMAGE : 0), 0, 0, null)) { if (fileMapping.IsInvalid) throw new MemoryMappedIONotSupportedException(string.Format("Could not create a file mapping object. File: {0}, error: {1:X8}", creator.theFileName, Marshal.GetLastWin32Error())); creator.data = MapViewOfFile(fileMapping, FILE_MAP_READ, 0, 0, UIntPtr.Zero); if (creator.data == IntPtr.Zero) throw new MemoryMappedIONotSupportedException(string.Format("Could not map file {0}. Error: {1:X8}", creator.theFileName, Marshal.GetLastWin32Error())); creator.dataLength = fileSize; creator.osType = OSType.Windows; } } } public static void Dispose(IntPtr addr) { if (addr != IntPtr.Zero) UnmapViewOfFile(addr); } } static class Unix { // Can't use SafeFileHandle. Seems like a bug in mono. You'll get // "_wapi_handle_unref_full: Attempting to unref unused handle 0xYYY" when Dispose() is called. [DllImport("libc")] static extern int open(string pathname, int flags); const int O_RDONLY = 0; [DllImport("libc")] static extern int close(int fd); [DllImport("libc", EntryPoint = "lseek", SetLastError = true)] static extern int lseek32(int fd, int offset, int whence); [DllImport("libc", EntryPoint = "lseek", SetLastError = true)] static extern long lseek64(int fd, long offset, int whence); const int SEEK_END = 2; [DllImport("libc", EntryPoint = "mmap", SetLastError = true)] static extern IntPtr mmap32(IntPtr addr, IntPtr length, int prot, int flags, int fd, int offset); [DllImport("libc", EntryPoint = "mmap", SetLastError = true)] static extern IntPtr mmap64(IntPtr addr, IntPtr length, int prot, int flags, int fd, long offset); const int PROT_READ = 1; const int MAP_PRIVATE = 0x02; [DllImport("libc")] static extern int munmap(IntPtr addr, IntPtr length); public static void Mmap(MemoryMappedFileStreamCreator creator, bool mapAsImage) { int fd = open(creator.theFileName, O_RDONLY); try { if (fd < 0) throw new IOException(string.Format("Could not open file {0} for reading. Error: {1}", creator.theFileName, fd)); long size; IntPtr data; if (IntPtr.Size == 4) { size = lseek32(fd, 0, SEEK_END); if (size == -1) throw new MemoryMappedIONotSupportedException(string.Format("Could not get length of {0} (lseek failed): {1}", creator.theFileName, Marshal.GetLastWin32Error())); data = mmap32(IntPtr.Zero, (IntPtr)size, PROT_READ, MAP_PRIVATE, fd, 0); if (data == new IntPtr(-1) || data == IntPtr.Zero) throw new MemoryMappedIONotSupportedException(string.Format("Could not map file {0}. Error: {1}", creator.theFileName, Marshal.GetLastWin32Error())); } else { size = lseek64(fd, 0, SEEK_END); if (size == -1) throw new MemoryMappedIONotSupportedException(string.Format("Could not get length of {0} (lseek failed): {1}", creator.theFileName, Marshal.GetLastWin32Error())); data = mmap64(IntPtr.Zero, (IntPtr)size, PROT_READ, MAP_PRIVATE, fd, 0); if (data == new IntPtr(-1) || data == IntPtr.Zero) throw new MemoryMappedIONotSupportedException(string.Format("Could not map file {0}. Error: {1}", creator.theFileName, Marshal.GetLastWin32Error())); } creator.data = data; creator.dataLength = size; creator.origDataLength = creator.dataLength; creator.osType = OSType.Unix; } finally { if (fd >= 0) close(fd); } } public static void Dispose(IntPtr addr, long size) { if (addr != IntPtr.Zero) munmap(addr, new IntPtr(size)); } } static bool canTryWindows = true; static bool canTryUnix = true; /// /// Creates a new if supported or returns /// null if the OS functions aren't supported. /// /// If is true, then the created /// that is used internally by the class, /// can only access bytes up to the file size, not to the end of the mapped image. You must /// set to the correct image length to access the full image. /// Name of the file /// true if we should map it as an executable /// If we can't open/map the file internal static MemoryMappedFileStreamCreator CreateWindows(string fileName, bool mapAsImage) { if (!canTryWindows) return null; var creator = new MemoryMappedFileStreamCreator(); creator.theFileName = GetFullPath(fileName); try { Windows.Mmap(creator, mapAsImage); return creator; } catch (EntryPointNotFoundException) { } catch (DllNotFoundException) { } canTryWindows = false; return null; } /// /// Creates a new if supported or returns /// null if the OS functions aren't supported. /// /// If is true, then the created /// that is used internally by the class, /// can only access bytes up to the file size, not to the end of the mapped image. You must /// set to the correct image length to access the full image. /// Name of the file /// NOT SUPPORTED. true if we should map it as an executable /// If we can't open/map the file internal static MemoryMappedFileStreamCreator CreateUnix(string fileName, bool mapAsImage) { if (!canTryUnix) return null; var creator = new MemoryMappedFileStreamCreator(); creator.theFileName = GetFullPath(fileName); try { Unix.Mmap(creator, mapAsImage); if (mapAsImage) { // Only check this if we know that mmap() works, i.e., if above call succeeds creator.Dispose(); throw new ArgumentException("mapAsImage == true is not supported on this OS"); } return creator; } catch (MemoryMappedIONotSupportedException ex) { Debug.WriteLine(string.Format("mmap'd IO didn't work: {0}", ex.Message)); } catch (EntryPointNotFoundException) { } catch (DllNotFoundException) { } canTryUnix = false; return null; } static string GetFullPath(string fileName) { try { return Path.GetFullPath(fileName); } catch { return fileName; } } /// ~MemoryMappedFileStreamCreator() { Dispose(false); } /// protected override void Dispose(bool disposing) { FreeMemoryMappedIoData(); base.Dispose(disposing); } /// /// true if memory mapped I/O is enabled /// public bool IsMemoryMappedIO { get { return dataAry == null; } } /// /// Call this to disable memory mapped I/O. This must only be called if no other code is /// trying to access the memory since that could lead to an exception. /// public void UnsafeDisableMemoryMappedIO() { if (dataAry != null) return; if (unsafeUseAddress) throw new InvalidOperationException("Can't convert to non-memory mapped I/O because the PDB reader uses the address. Use the managed PDB reader instead."); var newAry = new byte[Length]; Marshal.Copy(data, newAry, 0, newAry.Length); FreeMemoryMappedIoData(); dataLength = newAry.Length; dataAry = newAry; gcHandle = GCHandle.Alloc(dataAry, GCHandleType.Pinned); this.data = gcHandle.AddrOfPinnedObject(); } GCHandle gcHandle; byte[] dataAry; void FreeMemoryMappedIoData() { if (dataAry == null) { var origData = Interlocked.Exchange(ref data, IntPtr.Zero); if (origData != IntPtr.Zero) { dataLength = 0; switch (osType) { case OSType.Windows: Windows.Dispose(origData); break; case OSType.Unix: Unix.Dispose(origData, origDataLength); break; default: throw new InvalidOperationException("Shouldn't be here"); } } } if (gcHandle.IsAllocated) { try { gcHandle.Free(); } catch (InvalidOperationException) { } } dataAry = null; } } } dnlib-2.1_VS2010/src/IO/MemoryStreamCreator.cs000066400000000000000000000043341325033663500207620ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.IO; namespace dnlib.IO { /// /// Creates s to partially access a byte[] /// /// [DebuggerDisplay("byte[]: O:{dataOffset} L:{dataLength} {theFileName}")] sealed class MemoryStreamCreator : IImageStreamCreator { byte[] data; int dataOffset; int dataLength; string theFileName; /// /// The file name /// public string FileName { get { return theFileName; } set { theFileName = value; } } /// public long Length { get { return dataLength; } } /// /// Constructor /// /// The data public MemoryStreamCreator(byte[] data) : this(data, 0, data.Length) { } /// /// Constructor /// /// The data /// Start offset in /// Length of data starting from /// If one of the args is invalid public MemoryStreamCreator(byte[] data, int offset, int length) { if (offset < 0) throw new ArgumentOutOfRangeException("offset"); if (length < 0 || offset + length < offset) throw new ArgumentOutOfRangeException("length"); if (offset + length > data.Length) throw new ArgumentOutOfRangeException("length"); this.data = data; this.dataOffset = offset; this.dataLength = length; } /// public IImageStream Create(FileOffset offset, long length) { if (offset < 0 || length < 0) return MemoryImageStream.CreateEmpty(); int offs = (int)Math.Min((long)dataLength, (long)offset); int len = (int)Math.Min((long)dataLength - offs, length); return new MemoryImageStream(offset, data, dataOffset + offs, len); } /// public IImageStream CreateFull() { return new MemoryImageStream(0, data, dataOffset, dataLength); } /// public void Dispose() { data = null; dataOffset = 0; dataLength = 0; theFileName = null; } } } dnlib-2.1_VS2010/src/IO/UnmanagedMemoryImageStream.cs000066400000000000000000000151331325033663500222240ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; namespace dnlib.IO { /// /// IImageStream for unmanaged memory /// [DebuggerDisplay("FO:{fileOffset} S:{Length} A:{startAddr}")] sealed unsafe class UnmanagedMemoryImageStream : IImageStream { FileOffset fileOffset; long startAddr; long endAddr; long currentAddr; UnmanagedMemoryStreamCreator owner; bool ownOwner; /// /// Constructor /// /// Owner of memory /// File offset of data /// Address of data /// Length of data public unsafe UnmanagedMemoryImageStream(UnmanagedMemoryStreamCreator owner, FileOffset fileOffset, long baseAddr, long length) { this.fileOffset = fileOffset; this.startAddr = baseAddr; this.endAddr = baseAddr + length; this.currentAddr = this.startAddr; this.owner = owner; } /// /// Saves in this instance so it doesn't get garbage collected. /// /// A instance internal UnmanagedMemoryImageStream(UnmanagedMemoryStreamCreator creator) : this(creator, 0, 0, creator.Length) { this.ownOwner = true; } /// public FileOffset FileOffset { get { return fileOffset; } } /// /// Gets the start address of the memory this instance uses /// internal unsafe IntPtr StartAddress { get { return new IntPtr((byte*)owner.UnsafeUseAddress + startAddr); } } /// public unsafe long Length { get { return endAddr - startAddr; } } /// public unsafe long Position { get { return currentAddr - startAddr; } set { if (IntPtr.Size == 4 && (ulong)value > int.MaxValue) value = int.MaxValue; long newAddr = startAddr + value; if (newAddr < startAddr) newAddr = endAddr; currentAddr = newAddr; } } /// public unsafe IImageStream Create(FileOffset offset, long length) { if ((long)offset < 0 || length < 0) return MemoryImageStream.CreateEmpty(); long offs = Math.Min(Length, (long)offset); long len = Math.Min(Length - offs, length); return new UnmanagedMemoryImageStream(owner, (FileOffset)((long)fileOffset + (long)offset), startAddr + (long)offs, len); } /// public unsafe byte[] ReadBytes(int size) { if (size < 0) throw new IOException("Invalid size"); size = (int)Math.Min(size, Length - Math.Min(Length, Position)); var newData = new byte[size]; Marshal.Copy(new IntPtr((byte*)owner.Address + currentAddr), newData, 0, size); currentAddr += size; return newData; } /// public int Read(byte[] buffer, int offset, int length) { if (length < 0) throw new IOException("Invalid size"); length = (int)Math.Min(length, Length - Math.Min(Length, Position)); Marshal.Copy(new IntPtr((byte*)owner.Address + currentAddr), buffer, offset, length); currentAddr += length; return length; } /// public byte[] ReadBytesUntilByte(byte b) { long pos = GetPositionOf(b); if (pos == -1) return null; return ReadBytes((int)(pos - currentAddr)); } unsafe long GetPositionOf(byte b) { byte* pos = (byte*)owner.Address + currentAddr; byte* posStart = pos; var endPos = (byte*)owner.Address + endAddr; while (pos < endPos) { if (*pos == b) return currentAddr + (pos - posStart); pos++; } return -1; } /// public unsafe sbyte ReadSByte() { if (currentAddr >= endAddr) throw new IOException("Can't read one SByte"); return (sbyte)*((byte*)owner.Address + currentAddr++); } /// public unsafe byte ReadByte() { if (currentAddr >= endAddr) throw new IOException("Can't read one Byte"); return *((byte*)owner.Address + currentAddr++); } /// public unsafe short ReadInt16() { if (currentAddr + 1 >= endAddr) throw new IOException("Can't read one Int16"); short val = *(short*)((byte*)owner.Address + currentAddr); currentAddr += 2; return val; } /// public unsafe ushort ReadUInt16() { if (currentAddr + 1 >= endAddr) throw new IOException("Can't read one UInt16"); ushort val = *(ushort*)((byte*)owner.Address + currentAddr); currentAddr += 2; return val; } /// public unsafe int ReadInt32() { if (currentAddr + 3 >= endAddr) throw new IOException("Can't read one Int32"); int val = *(int*)((byte*)owner.Address + currentAddr); currentAddr += 4; return val; } /// public unsafe uint ReadUInt32() { if (currentAddr + 3 >= endAddr) throw new IOException("Can't read one UInt32"); uint val = *(uint*)((byte*)owner.Address + currentAddr); currentAddr += 4; return val; } /// public unsafe long ReadInt64() { if (currentAddr + 7 >= endAddr) throw new IOException("Can't read one Int64"); long val = *(long*)((byte*)owner.Address + currentAddr); currentAddr += 8; return val; } /// public unsafe ulong ReadUInt64() { if (currentAddr + 7 >= endAddr) throw new IOException("Can't read one UInt64"); ulong val = *(ulong*)((byte*)owner.Address + currentAddr); currentAddr += 8; return val; } /// public unsafe float ReadSingle() { if (currentAddr + 3 >= endAddr) throw new IOException("Can't read one Single"); var val = *(float*)((byte*)owner.Address + currentAddr); currentAddr += 4; return val; } /// public unsafe double ReadDouble() { if (currentAddr + 7 >= endAddr) throw new IOException("Can't read one Double"); var val = *(double*)((byte*)owner.Address + currentAddr); currentAddr += 8; return val; } /// public unsafe string ReadString(int chars) { if (IntPtr.Size == 4 && (uint)chars > (uint)int.MaxValue) throw new IOException("Not enough space to read the string"); if (currentAddr + chars * 2 < currentAddr || (chars != 0 && currentAddr + chars * 2 - 1 >= endAddr)) throw new IOException("Not enough space to read the string"); var s = new string((char*)((byte*)owner.Address + currentAddr), 0, chars); currentAddr += chars * 2; return s; } /// public void Dispose() { fileOffset = 0; startAddr = 0; endAddr = 0; currentAddr = 0; if (ownOwner && owner != null) owner.Dispose(); owner = null; } } } dnlib-2.1_VS2010/src/IO/UnmanagedMemoryStreamCreator.cs000066400000000000000000000054761325033663500226120ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.IO; namespace dnlib.IO { /// /// Creates s to partially access an /// unmanaged memory range /// /// [DebuggerDisplay("mem: D:{data} L:{dataLength} {theFileName}")] class UnmanagedMemoryStreamCreator : IImageStreamCreator { /// /// Address of data /// protected IntPtr data; /// /// Length of data /// protected long dataLength; /// /// Name of file /// protected string theFileName; /// /// The file name /// public string FileName { get { return theFileName; } set { theFileName = value; } } /// /// Size of the data /// public long Length { get { return dataLength; } set { dataLength = value; } } /// /// Returns the base address of the data /// public IntPtr Address { get { return data; } } public IntPtr UnsafeUseAddress { get { unsafeUseAddress = true; return data; } } protected bool unsafeUseAddress; /// /// Default constructor /// protected UnmanagedMemoryStreamCreator() { } /// /// Constructor for 0 bytes of data /// /// Pointer to the data public UnmanagedMemoryStreamCreator(IntPtr data) : this(data, 0) { } /// /// Constructor /// /// Pointer to the data /// Length of data /// If one of the args is invalid public UnmanagedMemoryStreamCreator(IntPtr data, long dataLength) { if (dataLength < 0) throw new ArgumentOutOfRangeException("dataLength"); this.data = data; this.dataLength = dataLength; } /// public unsafe IImageStream Create(FileOffset offset, long length) { if (offset < 0 || length < 0) return MemoryImageStream.CreateEmpty(); long offs = Math.Min((long)dataLength, (long)offset); long len = Math.Min((long)dataLength - offs, length); return new UnmanagedMemoryImageStream(this, offset, offs, len); } /// public IImageStream CreateFull() { return new UnmanagedMemoryImageStream(this, 0, 0, dataLength); } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose method /// /// true if called by protected virtual void Dispose(bool disposing) { if (disposing) { data = IntPtr.Zero; dataLength = 0; theFileName = null; } } } } dnlib-2.1_VS2010/src/PE/000077500000000000000000000000001325033663500144605ustar00rootroot00000000000000dnlib-2.1_VS2010/src/PE/Characteristics.cs000066400000000000000000000030671325033663500201300ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.PE { /// /// IMAGE_FILE_HEADER.Characteristics flags /// [Flags] public enum Characteristics : ushort { /// Relocation info stripped from file. RelocsStripped = 0x0001, /// File is executable (i.e. no unresolved externel references). ExecutableImage = 0x0002, /// Line nunbers stripped from file. LineNumsStripped = 0x0004, /// Local symbols stripped from file. LocalSymsStripped = 0x0008, /// Agressively trim working set AggressiveWsTrim = 0x0010, /// App can handle >2gb addresses LargeAddressAware = 0x0020, /// Reserved1 = 0x0040, /// Bytes of machine word are reversed. BytesReversedLo = 0x0080, /// 32 bit word machine. _32BitMachine = 0x0100, /// Debugging info stripped from file in .DBG file DebugStripped = 0x0200, /// If Image is on removable media, copy and run from the swap file. RemovableRunFromSwap= 0x0400, /// If Image is on Net, copy and run from the swap file. NetRunFromSwap = 0x0800, /// System File. System = 0x1000, /// File is a DLL. Dll = 0x2000, /// File should only be run on a UP machine UpSystemOnly = 0x4000, /// Bytes of machine word are reversed. BytesReversedHi = 0x8000, } } dnlib-2.1_VS2010/src/PE/DllCharacteristics.cs000066400000000000000000000024451325033663500205630ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.PE { /// /// IMAGE_OPTIONAL_HEADER.DllCharacteristics /// [Flags] public enum DllCharacteristics : ushort { /// Reserved1 = 0x0001, /// Reserved2 = 0x0002, /// Reserved3 = 0x0004, /// Reserved4 = 0x0008, /// Reserved5 = 0x0010, /// Image can handle a high entropy 64-bit virtual address space. HighEntropyVA = 0x0020, /// DLL can move. DynamicBase = 0x0040, /// Code Integrity Image ForceIntegrity = 0x0080, /// Image is NX compatible NxCompat = 0x0100, /// Image understands isolation and doesn't want it NoIsolation = 0x0200, /// Image does not use SEH. No SE handler may reside in this image NoSeh = 0x0400, /// Do not bind this image. NoBind = 0x0800, /// Image should execute in an AppContainer AppContainer = 0x1000, /// Driver uses WDM model WdmDriver = 0x2000, /// Image supports Control Flow Guard. GuardCf = 0x4000, /// TerminalServerAware = 0x8000, } } dnlib-2.1_VS2010/src/PE/IImageOptionalHeader.cs000066400000000000000000000070301325033663500207610ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.IO; namespace dnlib.PE { /// /// Interface for PE optional header classes /// public interface IImageOptionalHeader : IFileSection { /// /// Returns the Magic field /// ushort Magic { get; } /// /// Returns the MajorLinkerVersion field /// byte MajorLinkerVersion { get; } /// /// Returns the MinorLinkerVersion field /// byte MinorLinkerVersion { get; } /// /// Returns the SizeOfCode field /// uint SizeOfCode { get; } /// /// Returns the SizeOfInitializedData field /// uint SizeOfInitializedData { get; } /// /// Returns the SizeOfUninitializedData field /// uint SizeOfUninitializedData { get; } /// /// Returns the AddressOfEntryPoint field /// RVA AddressOfEntryPoint { get; } /// /// Returns the BaseOfCode field /// RVA BaseOfCode { get; } /// /// Returns the BaseOfData field /// RVA BaseOfData { get; } /// /// Returns the ImageBase field /// ulong ImageBase { get; } /// /// Returns the SectionAlignment field /// uint SectionAlignment { get; } /// /// Returns the FileAlignment field /// uint FileAlignment { get; } /// /// Returns the MajorOperatingSystemVersion field /// ushort MajorOperatingSystemVersion { get; } /// /// Returns the MinorOperatingSystemVersion field /// ushort MinorOperatingSystemVersion { get; } /// /// Returns the MajorImageVersion field /// ushort MajorImageVersion { get; } /// /// Returns the MinorImageVersion field /// ushort MinorImageVersion { get; } /// /// Returns the MajorSubsystemVersion field /// ushort MajorSubsystemVersion { get; } /// /// Returns the MinorSubsystemVersion field /// ushort MinorSubsystemVersion { get; } /// /// Returns the Win32VersionValue field /// uint Win32VersionValue { get; } /// /// Returns the SizeOfImage field /// uint SizeOfImage { get; } /// /// Returns the SizeOfHeaders field /// uint SizeOfHeaders { get; } /// /// Returns the CheckSum field /// uint CheckSum { get; } /// /// Returns the Subsystem field /// Subsystem Subsystem { get; } /// /// Returns the DllCharacteristics field /// DllCharacteristics DllCharacteristics { get; } /// /// Returns the SizeOfStackReserve field /// ulong SizeOfStackReserve { get; } /// /// Returns the SizeOfStackCommit field /// ulong SizeOfStackCommit { get; } /// /// Returns the SizeOfHeapReserve field /// ulong SizeOfHeapReserve { get; } /// /// Returns the SizeOfHeapCommit field /// ulong SizeOfHeapCommit { get; } /// /// Returns the LoaderFlags field /// uint LoaderFlags { get; } /// /// Returns the NumberOfRvaAndSizes field /// uint NumberOfRvaAndSizes { get; } /// /// Returns the DataDirectories field /// ImageDataDirectory[] DataDirectories { get; } } } dnlib-2.1_VS2010/src/PE/IPEImage.cs000066400000000000000000000126421325033663500163740ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using dnlib.IO; using dnlib.W32Resources; namespace dnlib.PE { /// /// Converts s to/from s /// public interface IRvaFileOffsetConverter { /// /// Converts a to an /// /// The file offset to convert /// The RVA RVA ToRVA(FileOffset offset); /// /// Converts an to a /// /// The RVA to convert /// The file offset FileOffset ToFileOffset(RVA rva); } /// /// Interface to access a PE image /// public interface IPEImage : IRvaFileOffsetConverter, IDisposable { /// /// true if image layout is the same as the raw PE image layout, false /// if it's the same layout as a PE image loaded by the OS PE loader. /// bool IsFileImageLayout { get; } /// /// true if some of the memory where the image is located could be unavailable. /// This could happen if it's been loaded by the OS loader. /// bool MayHaveInvalidAddresses { get; } /// /// The file name or null if data is not from a file /// string FileName { get; } /// /// Returns the DOS header /// ImageDosHeader ImageDosHeader { get; } /// /// Returns the NT headers /// ImageNTHeaders ImageNTHeaders { get; } /// /// Returns the section headers /// IList ImageSectionHeaders { get; } /// /// Returns the debug directories /// IList ImageDebugDirectories { get; } /// /// Gets/sets the Win32 resources. This is null if there are no Win32 resources. /// Win32Resources Win32Resources { get; set; } /// /// Creates a stream to access part of the PE image from /// to the end of the image /// /// File offset /// A new stream /// If the arg is invalid IImageStream CreateStream(FileOffset offset); /// /// Creates a stream to access part of the PE image from /// with length /// /// File offset /// Length of data /// A new stream /// If any arg is invalid IImageStream CreateStream(FileOffset offset, long length); /// /// Creates a stream to access the full PE image /// /// A new stream IImageStream CreateFullStream(); /// /// Call this to disable memory mapped I/O if it was used to open the file. This must only /// be called if no other code is trying to access the memory since that could lead to an /// exception. /// void UnsafeDisableMemoryMappedIO(); /// /// true if memory mapped I/O is enabled /// bool IsMemoryMappedIO { get; } } public static partial class PEExtensions { /// /// Creates a stream to access part of the PE image from /// to the end of the image /// /// this /// RVA /// A new stream /// If the arg is invalid public static IImageStream CreateStream(this IPEImage self, RVA rva) { return self.CreateStream(self.ToFileOffset(rva)); } /// /// Creates a stream to access part of the PE image from /// with length /// /// this /// RVA /// Length of data /// A new stream /// If any arg is invalid public static IImageStream CreateStream(this IPEImage self, RVA rva, long length) { return self.CreateStream(self.ToFileOffset(rva), length); } /// /// Reads all bytes from the PE image. This may fail if the PE image has been loaded /// by the OS loader since there may be memory holes. /// /// this /// All bytes of the PE image public static byte[] GetImageAsByteArray(this IPEImage self) { using (var reader = self.CreateFullStream()) return reader.ReadAllBytes(); } /// /// Finds a /// /// this /// Type /// Name /// Language ID /// The or null if none found public static ResourceData FindWin32ResourceData(this IPEImage self, ResourceName type, ResourceName name, ResourceName langId) { var w32Resources = self.Win32Resources; return w32Resources == null ? null : w32Resources.Find(type, name, langId); } } } dnlib-2.1_VS2010/src/PE/IPEType.cs000066400000000000000000000014411325033663500162660ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using dnlib.IO; namespace dnlib.PE { /// /// Converts a to/from an /// interface IPEType { /// /// Converts a to an /// /// The PEInfo context /// The file offset to convert /// The RVA RVA ToRVA(PEInfo peInfo, FileOffset offset); /// /// Converts an to a /// /// The PEInfo context /// The RVA to convert /// The file offset FileOffset ToFileOffset(PEInfo peInfo, RVA rva); } } dnlib-2.1_VS2010/src/PE/ImageDataDirectory.cs000066400000000000000000000023471325033663500205160ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using dnlib.IO; namespace dnlib.PE { /// /// Represents the IMAGE_DATA_DIRECTORY PE section /// [DebuggerDisplay("{virtualAddress} {dataSize}")] public sealed class ImageDataDirectory : FileSection { readonly RVA virtualAddress; readonly uint dataSize; /// /// Returns the IMAGE_DATA_DIRECTORY.VirtualAddress field /// public RVA VirtualAddress { get { return virtualAddress; } } /// /// Returns the IMAGE_DATA_DIRECTORY.Size field /// public uint Size { get { return dataSize; } } /// /// Default constructor /// public ImageDataDirectory() { } /// /// Constructor /// /// PE file reader pointing to the start of this section /// Verify section /// Thrown if verification fails public ImageDataDirectory(IImageStream reader, bool verify) { SetStartOffset(reader); this.virtualAddress = (RVA)reader.ReadUInt32(); this.dataSize = reader.ReadUInt32(); SetEndoffset(reader); } } } dnlib-2.1_VS2010/src/PE/ImageDebugDirectory.cs000066400000000000000000000046161325033663500206740ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using dnlib.IO; namespace dnlib.PE { /// /// A IMAGE_DEBUG_DIRECTORY /// [DebuggerDisplay("{type}: TS:{timeDateStamp,h} V:{majorVersion,d}.{minorVersion,d} SZ:{sizeOfData} RVA:{addressOfRawData,h} FO:{pointerToRawData,h}")] public sealed class ImageDebugDirectory : FileSection { readonly uint characteristics; readonly uint timeDateStamp; readonly ushort majorVersion; readonly ushort minorVersion; readonly ImageDebugType type; readonly uint sizeOfData; readonly uint addressOfRawData; readonly uint pointerToRawData; /// /// Gets the characteristics (reserved) /// public uint Characteristics { get { return characteristics; } } /// /// Gets the timestamp /// public uint TimeDateStamp { get { return timeDateStamp; } } /// /// Gets the major version /// public ushort MajorVersion { get { return majorVersion; } } /// /// Gets the minor version /// public ushort MinorVersion { get { return minorVersion; } } /// /// Gets the type /// public ImageDebugType Type { get { return type; } } /// /// Gets the size of data /// public uint SizeOfData { get { return sizeOfData; } } /// /// RVA of the data /// public RVA AddressOfRawData { get { return (RVA)addressOfRawData; } } /// /// File offset of the data /// public FileOffset PointerToRawData { get { return (FileOffset)pointerToRawData; } } /// /// Constructor /// /// PE file reader pointing to the start of this section /// Verify section /// Thrown if verification fails public ImageDebugDirectory(IImageStream reader, bool verify) { SetStartOffset(reader); characteristics = reader.ReadUInt32(); timeDateStamp = reader.ReadUInt32(); majorVersion = reader.ReadUInt16(); minorVersion = reader.ReadUInt16(); type = (ImageDebugType)reader.ReadUInt32(); sizeOfData = reader.ReadUInt32(); addressOfRawData = reader.ReadUInt32(); pointerToRawData = reader.ReadUInt32(); SetEndoffset(reader); } } } dnlib-2.1_VS2010/src/PE/ImageDebugType.cs000066400000000000000000000015431325033663500176450ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.PE { /// /// Image debug type, see IMAGE_DEBUG_TYPE_* in winnt.n /// public enum ImageDebugType : uint { #pragma warning disable 1591 // Missing XML comment for publicly visible type or member Unknown = 0, Coff = 1, /// /// Contains PDB info /// CodeView = 2, FPO = 3, Misc = 4, Exception = 5, Fixup = 6, OmapToSrc = 7, OmapFromSrc = 8, Borland = 9, Reserved10 = 10, CLSID = 11, VcFeature = 12, POGO = 13, ILTCG = 14, MPX = 15, /// /// It's a deterministic (reproducible) PE file /// Repro = 16, /// /// Embedded portable PDB data /// EmbeddedPortablePdb = 17, #pragma warning restore 1591 // Missing XML comment for publicly visible type or member } } dnlib-2.1_VS2010/src/PE/ImageDosHeader.cs000066400000000000000000000017331325033663500176140ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; namespace dnlib.PE { /// /// Represents the IMAGE_DOS_HEADER PE section /// public sealed class ImageDosHeader : FileSection { readonly uint ntHeadersOffset; /// /// File offset of the NT headers /// public uint NTHeadersOffset { get { return ntHeadersOffset; } } /// /// Constructor /// /// PE file reader /// Verify section /// Thrown if verification fails public ImageDosHeader(IImageStream reader, bool verify) { SetStartOffset(reader); ushort sig = reader.ReadUInt16(); if (verify && sig != 0x5A4D) throw new BadImageFormatException("Invalid DOS signature"); reader.Position = (long)startOffset + 0x3C; this.ntHeadersOffset = reader.ReadUInt32(); SetEndoffset(reader); } } } dnlib-2.1_VS2010/src/PE/ImageFileHeader.cs000066400000000000000000000047161325033663500177520ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; namespace dnlib.PE { /// /// Represents the IMAGE_FILE_HEADER PE section /// public sealed class ImageFileHeader : FileSection { readonly Machine machine; readonly ushort numberOfSections; readonly uint timeDateStamp; readonly uint pointerToSymbolTable; readonly uint numberOfSymbols; readonly ushort sizeOfOptionalHeader; readonly Characteristics characteristics; /// /// Returns the IMAGE_FILE_HEADER.Machine field /// public Machine Machine { get { return machine; } } /// /// Returns the IMAGE_FILE_HEADER.NumberOfSections field /// public int NumberOfSections { get { return numberOfSections; } } /// /// Returns the IMAGE_FILE_HEADER.TimeDateStamp field /// public uint TimeDateStamp { get { return timeDateStamp; } } /// /// Returns the IMAGE_FILE_HEADER.PointerToSymbolTable field /// public uint PointerToSymbolTable { get { return pointerToSymbolTable; } } /// /// Returns the IMAGE_FILE_HEADER.NumberOfSymbols field /// public uint NumberOfSymbols { get { return numberOfSymbols; } } /// /// Returns the IMAGE_FILE_HEADER.SizeOfOptionalHeader field /// public uint SizeOfOptionalHeader { get { return sizeOfOptionalHeader; } } /// /// Returns the IMAGE_FILE_HEADER.Characteristics field /// public Characteristics Characteristics { get { return characteristics; } } /// /// Constructor /// /// PE file reader pointing to the start of this section /// Verify section /// Thrown if verification fails public ImageFileHeader(IImageStream reader, bool verify) { SetStartOffset(reader); this.machine = (Machine)reader.ReadUInt16(); this.numberOfSections = reader.ReadUInt16(); this.timeDateStamp = reader.ReadUInt32(); this.pointerToSymbolTable = reader.ReadUInt32(); this.numberOfSymbols = reader.ReadUInt32(); this.sizeOfOptionalHeader = reader.ReadUInt16(); this.characteristics = (Characteristics)reader.ReadUInt16(); SetEndoffset(reader); if (verify && this.sizeOfOptionalHeader == 0) throw new BadImageFormatException("Invalid SizeOfOptionalHeader"); } } } dnlib-2.1_VS2010/src/PE/ImageNTHeaders.cs000066400000000000000000000044641325033663500175770ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; namespace dnlib.PE { /// /// Represents the IMAGE_NT_HEADERS PE section /// public sealed class ImageNTHeaders : FileSection { readonly uint signature; readonly ImageFileHeader imageFileHeader; readonly IImageOptionalHeader imageOptionalHeader; /// /// Returns the IMAGE_NT_HEADERS.Signature field /// public uint Signature { get { return signature; } } /// /// Returns the IMAGE_NT_HEADERS.FileHeader field /// public ImageFileHeader FileHeader { get { return imageFileHeader; } } /// /// Returns the IMAGE_NT_HEADERS.OptionalHeader field /// public IImageOptionalHeader OptionalHeader { get { return imageOptionalHeader; } } /// /// Constructor /// /// PE file reader pointing to the start of this section /// Verify section /// Thrown if verification fails public ImageNTHeaders(IImageStream reader, bool verify) { SetStartOffset(reader); this.signature = reader.ReadUInt32(); if (verify && this.signature != 0x4550) throw new BadImageFormatException("Invalid NT headers signature"); this.imageFileHeader = new ImageFileHeader(reader, verify); this.imageOptionalHeader = CreateImageOptionalHeader(reader, verify); SetEndoffset(reader); } /// /// Creates an IImageOptionalHeader /// /// PE file reader pointing to the start of the optional header /// Verify section /// The created IImageOptionalHeader /// Thrown if verification fails IImageOptionalHeader CreateImageOptionalHeader(IImageStream reader, bool verify) { ushort magic = reader.ReadUInt16(); reader.Position -= 2; switch (magic) { case 0x010B: return new ImageOptionalHeader32(reader, imageFileHeader.SizeOfOptionalHeader, verify); case 0x020B: return new ImageOptionalHeader64(reader, imageFileHeader.SizeOfOptionalHeader, verify); default: throw new BadImageFormatException("Invalid optional header magic"); } } } } dnlib-2.1_VS2010/src/PE/ImageOptionalHeader32.cs000066400000000000000000000220351325033663500210170ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; namespace dnlib.PE { /// /// Represents the IMAGE_OPTIONAL_HEADER (32-bit) PE section /// public sealed class ImageOptionalHeader32 : FileSection, IImageOptionalHeader { readonly ushort magic; readonly byte majorLinkerVersion; readonly byte minorLinkerVersion; readonly uint sizeOfCode; readonly uint sizeOfInitializedData; readonly uint sizeOfUninitializedData; readonly RVA addressOfEntryPoint; readonly RVA baseOfCode; readonly RVA baseOfData; readonly uint imageBase; readonly uint sectionAlignment; readonly uint fileAlignment; readonly ushort majorOperatingSystemVersion; readonly ushort minorOperatingSystemVersion; readonly ushort majorImageVersion; readonly ushort minorImageVersion; readonly ushort majorSubsystemVersion; readonly ushort minorSubsystemVersion; readonly uint win32VersionValue; readonly uint sizeOfImage; readonly uint sizeOfHeaders; readonly uint checkSum; readonly Subsystem subsystem; readonly DllCharacteristics dllCharacteristics; readonly uint sizeOfStackReserve; readonly uint sizeOfStackCommit; readonly uint sizeOfHeapReserve; readonly uint sizeOfHeapCommit; readonly uint loaderFlags; readonly uint numberOfRvaAndSizes; readonly ImageDataDirectory[] dataDirectories = new ImageDataDirectory[16]; /// /// Returns the IMAGE_OPTIONAL_HEADER.Magic field /// public ushort Magic { get { return magic; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.MajorLinkerVersion field /// public byte MajorLinkerVersion { get { return majorLinkerVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.MinorLinkerVersion field /// public byte MinorLinkerVersion { get { return minorLinkerVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.SizeOfCode field /// public uint SizeOfCode { get { return sizeOfCode; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.SizeOfInitializedData field /// public uint SizeOfInitializedData { get { return sizeOfInitializedData; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.SizeOfUninitializedData field /// public uint SizeOfUninitializedData { get { return sizeOfUninitializedData; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.AddressOfEntryPoint field /// public RVA AddressOfEntryPoint { get { return addressOfEntryPoint; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.BaseOfCode field /// public RVA BaseOfCode { get { return baseOfCode; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.BaseOfData field /// public RVA BaseOfData { get { return baseOfData; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.ImageBase field /// public ulong ImageBase { get { return imageBase; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.SectionAlignment field /// public uint SectionAlignment { get { return sectionAlignment; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.FileAlignment field /// public uint FileAlignment { get { return fileAlignment; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.MajorOperatingSystemVersion field /// public ushort MajorOperatingSystemVersion { get { return majorOperatingSystemVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.MinorOperatingSystemVersion field /// public ushort MinorOperatingSystemVersion { get { return minorOperatingSystemVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.MajorImageVersion field /// public ushort MajorImageVersion { get { return majorImageVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.MinorImageVersion field /// public ushort MinorImageVersion { get { return minorImageVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.MajorSubsystemVersion field /// public ushort MajorSubsystemVersion { get { return majorSubsystemVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.MinorSubsystemVersion field /// public ushort MinorSubsystemVersion { get { return minorSubsystemVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.Win32VersionValue field /// public uint Win32VersionValue { get { return win32VersionValue; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.SizeOfImage field /// public uint SizeOfImage { get { return sizeOfImage; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.SizeOfHeaders field /// public uint SizeOfHeaders { get { return sizeOfHeaders; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.CheckSum field /// public uint CheckSum { get { return checkSum; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.Subsystem field /// public Subsystem Subsystem { get { return subsystem; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.DllCharacteristics field /// public DllCharacteristics DllCharacteristics { get { return dllCharacteristics; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.SizeOfStackReserve field /// public ulong SizeOfStackReserve { get { return sizeOfStackReserve; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.SizeOfStackCommit field /// public ulong SizeOfStackCommit { get { return sizeOfStackCommit; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.SizeOfHeapReserve field /// public ulong SizeOfHeapReserve { get { return sizeOfHeapReserve; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.SizeOfHeapCommit field /// public ulong SizeOfHeapCommit { get { return sizeOfHeapCommit; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.LoaderFlags field /// public uint LoaderFlags { get { return loaderFlags; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.NumberOfRvaAndSizes field /// public uint NumberOfRvaAndSizes { get { return numberOfRvaAndSizes; } } /// /// Returns the IMAGE_OPTIONAL_HEADER.DataDirectories field /// public ImageDataDirectory[] DataDirectories { get { return dataDirectories; } } /// /// Constructor /// /// PE file reader pointing to the start of this section /// Total size of this optional header (from the file header) /// Verify section /// Thrown if verification fails public ImageOptionalHeader32(IImageStream reader, uint totalSize, bool verify) { if (totalSize < 0x60) throw new BadImageFormatException("Invalid optional header size"); if (verify && reader.Position + totalSize > reader.Length) throw new BadImageFormatException("Invalid optional header size"); SetStartOffset(reader); this.magic = reader.ReadUInt16(); this.majorLinkerVersion = reader.ReadByte(); this.minorLinkerVersion = reader.ReadByte(); this.sizeOfCode = reader.ReadUInt32(); this.sizeOfInitializedData = reader.ReadUInt32(); this.sizeOfUninitializedData = reader.ReadUInt32(); this.addressOfEntryPoint = (RVA)reader.ReadUInt32(); this.baseOfCode = (RVA)reader.ReadUInt32(); this.baseOfData = (RVA)reader.ReadUInt32(); this.imageBase = reader.ReadUInt32(); this.sectionAlignment = reader.ReadUInt32(); this.fileAlignment = reader.ReadUInt32(); this.majorOperatingSystemVersion = reader.ReadUInt16(); this.minorOperatingSystemVersion = reader.ReadUInt16(); this.majorImageVersion = reader.ReadUInt16(); this.minorImageVersion = reader.ReadUInt16(); this.majorSubsystemVersion = reader.ReadUInt16(); this.minorSubsystemVersion = reader.ReadUInt16(); this.win32VersionValue = reader.ReadUInt32(); this.sizeOfImage = reader.ReadUInt32(); this.sizeOfHeaders = reader.ReadUInt32(); this.checkSum = reader.ReadUInt32(); this.subsystem = (Subsystem)reader.ReadUInt16(); this.dllCharacteristics = (DllCharacteristics)reader.ReadUInt16(); this.sizeOfStackReserve = reader.ReadUInt32(); this.sizeOfStackCommit = reader.ReadUInt32(); this.sizeOfHeapReserve = reader.ReadUInt32(); this.sizeOfHeapCommit = reader.ReadUInt32(); this.loaderFlags = reader.ReadUInt32(); this.numberOfRvaAndSizes = reader.ReadUInt32(); for (int i = 0; i < dataDirectories.Length; i++) { uint len = (uint)(reader.Position - startOffset); if (len + 8 <= totalSize) dataDirectories[i] = new ImageDataDirectory(reader, verify); else dataDirectories[i] = new ImageDataDirectory(); } reader.Position = (long)startOffset + totalSize; SetEndoffset(reader); } } } dnlib-2.1_VS2010/src/PE/ImageOptionalHeader64.cs000066400000000000000000000220261325033663500210240ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; namespace dnlib.PE { /// /// Represents the IMAGE_OPTIONAL_HEADER64 PE section /// public sealed class ImageOptionalHeader64 : FileSection, IImageOptionalHeader { readonly ushort magic; readonly byte majorLinkerVersion; readonly byte minorLinkerVersion; readonly uint sizeOfCode; readonly uint sizeOfInitializedData; readonly uint sizeOfUninitializedData; readonly RVA addressOfEntryPoint; readonly RVA baseOfCode; readonly ulong imageBase; readonly uint sectionAlignment; readonly uint fileAlignment; readonly ushort majorOperatingSystemVersion; readonly ushort minorOperatingSystemVersion; readonly ushort majorImageVersion; readonly ushort minorImageVersion; readonly ushort majorSubsystemVersion; readonly ushort minorSubsystemVersion; readonly uint win32VersionValue; readonly uint sizeOfImage; readonly uint sizeOfHeaders; readonly uint checkSum; readonly Subsystem subsystem; readonly DllCharacteristics dllCharacteristics; readonly ulong sizeOfStackReserve; readonly ulong sizeOfStackCommit; readonly ulong sizeOfHeapReserve; readonly ulong sizeOfHeapCommit; readonly uint loaderFlags; readonly uint numberOfRvaAndSizes; readonly ImageDataDirectory[] dataDirectories = new ImageDataDirectory[16]; /// /// Returns the IMAGE_OPTIONAL_HEADER64.Magic field /// public ushort Magic { get { return magic; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.MajorLinkerVersion field /// public byte MajorLinkerVersion { get { return majorLinkerVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.MinorLinkerVersion field /// public byte MinorLinkerVersion { get { return minorLinkerVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.SizeOfCode field /// public uint SizeOfCode { get { return sizeOfCode; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.SizeOfInitializedData field /// public uint SizeOfInitializedData { get { return sizeOfInitializedData; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.SizeOfUninitializedData field /// public uint SizeOfUninitializedData { get { return sizeOfUninitializedData; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.AddressOfEntryPoint field /// public RVA AddressOfEntryPoint { get { return addressOfEntryPoint; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.BaseOfCode field /// public RVA BaseOfCode { get { return baseOfCode; } } /// /// Returns 0 since BaseOfData is not present in IMAGE_OPTIONAL_HEADER64 /// public RVA BaseOfData { get { return 0; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.ImageBase field /// public ulong ImageBase { get { return imageBase; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.SectionAlignment field /// public uint SectionAlignment { get { return sectionAlignment; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.FileAlignment field /// public uint FileAlignment { get { return fileAlignment; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.MajorOperatingSystemVersion field /// public ushort MajorOperatingSystemVersion { get { return majorOperatingSystemVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.MinorOperatingSystemVersion field /// public ushort MinorOperatingSystemVersion { get { return minorOperatingSystemVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.MajorImageVersion field /// public ushort MajorImageVersion { get { return majorImageVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.MinorImageVersion field /// public ushort MinorImageVersion { get { return minorImageVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.MajorSubsystemVersion field /// public ushort MajorSubsystemVersion { get { return majorSubsystemVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.MinorSubsystemVersion field /// public ushort MinorSubsystemVersion { get { return minorSubsystemVersion; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.Win32VersionValue field /// public uint Win32VersionValue { get { return win32VersionValue; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.SizeOfImage field /// public uint SizeOfImage { get { return sizeOfImage; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.SizeOfHeaders field /// public uint SizeOfHeaders { get { return sizeOfHeaders; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.CheckSum field /// public uint CheckSum { get { return checkSum; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.Subsystem field /// public Subsystem Subsystem { get { return subsystem; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.DllCharacteristics field /// public DllCharacteristics DllCharacteristics { get { return dllCharacteristics; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.SizeOfStackReserve field /// public ulong SizeOfStackReserve { get { return sizeOfStackReserve; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.SizeOfStackCommit field /// public ulong SizeOfStackCommit { get { return sizeOfStackCommit; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.SizeOfHeapReserve field /// public ulong SizeOfHeapReserve { get { return sizeOfHeapReserve; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.SizeOfHeapCommit field /// public ulong SizeOfHeapCommit { get { return sizeOfHeapCommit; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.LoaderFlags field /// public uint LoaderFlags { get { return loaderFlags; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.NumberOfRvaAndSizes field /// public uint NumberOfRvaAndSizes { get { return numberOfRvaAndSizes; } } /// /// Returns the IMAGE_OPTIONAL_HEADER64.DataDirectories field /// public ImageDataDirectory[] DataDirectories { get { return dataDirectories; } } /// /// Constructor /// /// PE file reader pointing to the start of this section /// Total size of this optional header (from the file header) /// Verify section /// Thrown if verification fails public ImageOptionalHeader64(IImageStream reader, uint totalSize, bool verify) { if (totalSize < 0x70) throw new BadImageFormatException("Invalid optional header size"); if (verify && reader.Position + totalSize > reader.Length) throw new BadImageFormatException("Invalid optional header size"); SetStartOffset(reader); this.magic = reader.ReadUInt16(); this.majorLinkerVersion = reader.ReadByte(); this.minorLinkerVersion = reader.ReadByte(); this.sizeOfCode = reader.ReadUInt32(); this.sizeOfInitializedData = reader.ReadUInt32(); this.sizeOfUninitializedData = reader.ReadUInt32(); this.addressOfEntryPoint = (RVA)reader.ReadUInt32(); this.baseOfCode = (RVA)reader.ReadUInt32(); this.imageBase = reader.ReadUInt64(); this.sectionAlignment = reader.ReadUInt32(); this.fileAlignment = reader.ReadUInt32(); this.majorOperatingSystemVersion = reader.ReadUInt16(); this.minorOperatingSystemVersion = reader.ReadUInt16(); this.majorImageVersion = reader.ReadUInt16(); this.minorImageVersion = reader.ReadUInt16(); this.majorSubsystemVersion = reader.ReadUInt16(); this.minorSubsystemVersion = reader.ReadUInt16(); this.win32VersionValue = reader.ReadUInt32(); this.sizeOfImage = reader.ReadUInt32(); this.sizeOfHeaders = reader.ReadUInt32(); this.checkSum = reader.ReadUInt32(); this.subsystem = (Subsystem)reader.ReadUInt16(); this.dllCharacteristics = (DllCharacteristics)reader.ReadUInt16(); this.sizeOfStackReserve = reader.ReadUInt64(); this.sizeOfStackCommit = reader.ReadUInt64(); this.sizeOfHeapReserve = reader.ReadUInt64(); this.sizeOfHeapCommit = reader.ReadUInt64(); this.loaderFlags = reader.ReadUInt32(); this.numberOfRvaAndSizes = reader.ReadUInt32(); for (int i = 0; i < dataDirectories.Length; i++) { uint len = (uint)(reader.Position - startOffset); if (len + 8 <= totalSize) dataDirectories[i] = new ImageDataDirectory(reader, verify); else dataDirectories[i] = new ImageDataDirectory(); } reader.Position = (long)startOffset + totalSize; SetEndoffset(reader); } } } dnlib-2.1_VS2010/src/PE/ImageSectionHeader.cs000066400000000000000000000072311325033663500204720ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Diagnostics; using System.Text; using dnlib.IO; namespace dnlib.PE { /// /// Represents the IMAGE_SECTION_HEADER PE section /// [DebuggerDisplay("RVA:{virtualAddress} VS:{virtualSize} FO:{pointerToRawData} FS:{sizeOfRawData} {displayName}")] public sealed class ImageSectionHeader : FileSection { readonly string displayName; readonly byte[] name; readonly uint virtualSize; readonly RVA virtualAddress; readonly uint sizeOfRawData; readonly uint pointerToRawData; readonly uint pointerToRelocations; readonly uint pointerToLinenumbers; readonly ushort numberOfRelocations; readonly ushort numberOfLinenumbers; readonly uint characteristics; /// /// Returns the human readable section name, ignoring everything after /// the first nul byte /// public string DisplayName { get { return displayName; } } /// /// Returns the IMAGE_SECTION_HEADER.Name field /// public byte[] Name { get { return name; } } /// /// Returns the IMAGE_SECTION_HEADER.VirtualSize field /// public uint VirtualSize { get { return virtualSize; } } /// /// Returns the IMAGE_SECTION_HEADER.VirtualAddress field /// public RVA VirtualAddress { get { return virtualAddress; } } /// /// Returns the IMAGE_SECTION_HEADER.SizeOfRawData field /// public uint SizeOfRawData { get { return sizeOfRawData; } } /// /// Returns the IMAGE_SECTION_HEADER.PointerToRawData field /// public uint PointerToRawData { get { return pointerToRawData; } } /// /// Returns the IMAGE_SECTION_HEADER.PointerToRelocations field /// public uint PointerToRelocations { get { return pointerToRelocations; } } /// /// Returns the IMAGE_SECTION_HEADER.PointerToLinenumbers field /// public uint PointerToLinenumbers { get { return pointerToLinenumbers; } } /// /// Returns the IMAGE_SECTION_HEADER.NumberOfRelocations field /// public ushort NumberOfRelocations { get { return numberOfRelocations; } } /// /// Returns the IMAGE_SECTION_HEADER.NumberOfLinenumbers field /// public ushort NumberOfLinenumbers { get { return numberOfLinenumbers; } } /// /// Returns the IMAGE_SECTION_HEADER.Characteristics field /// public uint Characteristics { get { return characteristics; } } /// /// Constructor /// /// PE file reader pointing to the start of this section /// Verify section /// Thrown if verification fails public ImageSectionHeader(IImageStream reader, bool verify) { SetStartOffset(reader); this.name = reader.ReadBytes(8); this.virtualSize = reader.ReadUInt32(); this.virtualAddress = (RVA)reader.ReadUInt32(); this.sizeOfRawData = reader.ReadUInt32(); this.pointerToRawData = reader.ReadUInt32(); this.pointerToRelocations = reader.ReadUInt32(); this.pointerToLinenumbers = reader.ReadUInt32(); this.numberOfRelocations = reader.ReadUInt16(); this.numberOfLinenumbers = reader.ReadUInt16(); this.characteristics = reader.ReadUInt32(); SetEndoffset(reader); displayName = ToString(name); } static string ToString(byte[] name) { var sb = new StringBuilder(name.Length); foreach (var b in name) { if (b == 0) break; sb.Append((char)b); } return sb.ToString(); } } } dnlib-2.1_VS2010/src/PE/Machine.cs000066400000000000000000000034701325033663500163570ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.PE { /// /// IMAGE_FILE_HEADER.Machine enum /// public enum Machine : ushort { /// Unknown machine Unknown = 0, /// x86 I386 = 0x014C, /// MIPS little-endian, 0x160 big-endian R3000 = 0x0162, /// MIPS little-endian R4000 = 0x0166, /// MIPS little-endian R10000 = 0x0168, /// MIPS little-endian WCE v2 WCEMIPSV2 = 0x0169, /// Alpha_AXP ALPHA = 0x0184, /// SH3 little-endian SH3 = 0x01A2, /// SH3DSP = 0x01A3, /// SH3E little-endian SH3E = 0x01A4, /// SH4 little-endian SH4 = 0x01A6, /// SH5 SH5 = 0x01A8, /// ARM Little-Endian ARM = 0x01C0, /// ARM Thumb/Thumb-2 Little-Endian THUMB = 0x01C2, /// ARM Thumb-2 Little-Endian ARMNT = 0x01C4, /// AM33 = 0x01D3, /// IBM PowerPC Little-Endian POWERPC = 0x01F0, /// POWERPCFP = 0x01F1, /// IA-64 IA64 = 0x0200, /// MIPS16 = 0x0266, /// ALPHA64 = 0x0284, /// MIPSFPU = 0x0366, /// MIPSFPU16 = 0x0466, /// Infineon TRICORE = 0x0520, /// CEF = 0x0CEF, /// EFI Byte Code EBC = 0x0EBC, /// x64 AMD64 = 0x8664, /// M32R little-endian M32R = 0x9041, /// ARM64 = 0xAA64, /// CEE = 0xC0EE, } } dnlib-2.1_VS2010/src/PE/PEExtensions.cs000066400000000000000000000015731325033663500174010ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.IO; namespace dnlib.PE { /// /// Extension methods /// public static partial class PEExtensions { /// /// Calculates a PE checksum /// /// Reader /// Length of image /// Offset of checksum /// PE checksum internal static uint CalculatePECheckSum(this BinaryReader reader, long length, long checkSumOffset) { uint checkSum = 0; for (long i = 0; i < length; i += 2) { if (i == checkSumOffset) { reader.ReadUInt32(); i += 2; continue; } checkSum += reader.ReadUInt16(); checkSum = (ushort)(checkSum + (checkSum >> 16)); } ulong cks = (ulong)checkSum + (ulong)length; return (uint)cks + (uint)(cks >> 32); } } } dnlib-2.1_VS2010/src/PE/PEImage.cs000066400000000000000000000272731325033663500162710ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.IO; using dnlib.IO; using dnlib.Utils; using dnlib.W32Resources; using dnlib.Threading; namespace dnlib.PE { /// /// Image layout /// public enum ImageLayout { /// /// Use this if the PE file has a normal structure (eg. it's been read from a file on disk) /// File, /// /// Use this if the PE file has been loaded into memory by the OS PE file loader /// Memory, } /// /// Accesses a PE file /// public sealed class PEImage : IPEImage { // Default to false because an OS loaded PE image may contain memory holes. If there // are memory holes, other code (eg. .NET resource creator) must verify that all memory // is available, which will be slower. const bool USE_MEMORY_LAYOUT_WITH_MAPPED_FILES = false; static readonly IPEType MemoryLayout = new MemoryPEType(); static readonly IPEType FileLayout = new FilePEType(); IImageStream imageStream; IImageStreamCreator imageStreamCreator; IPEType peType; PEInfo peInfo; UserValue win32Resources; #if THREAD_SAFE readonly Lock theLock = Lock.Create(); #endif sealed class FilePEType : IPEType { /// public RVA ToRVA(PEInfo peInfo, FileOffset offset) { return peInfo.ToRVA(offset); } /// public FileOffset ToFileOffset(PEInfo peInfo, RVA rva) { return peInfo.ToFileOffset(rva); } } sealed class MemoryPEType : IPEType { /// public RVA ToRVA(PEInfo peInfo, FileOffset offset) { return (RVA)offset; } /// public FileOffset ToFileOffset(PEInfo peInfo, RVA rva) { return (FileOffset)rva; } } /// public bool IsFileImageLayout { get { return peType is FilePEType; } } /// public bool MayHaveInvalidAddresses { get { return !IsFileImageLayout; } } /// public string FileName { get { return imageStreamCreator.FileName; } } /// public ImageDosHeader ImageDosHeader { get { return peInfo.ImageDosHeader; } } /// public ImageNTHeaders ImageNTHeaders { get { return peInfo.ImageNTHeaders; } } /// public IList ImageSectionHeaders { get { return peInfo.ImageSectionHeaders; } } /// public IList ImageDebugDirectories { get { if (imageDebugDirectories == null) imageDebugDirectories = ReadImageDebugDirectories(); return imageDebugDirectories; } } ImageDebugDirectory[] imageDebugDirectories; /// public Win32Resources Win32Resources { get { return win32Resources.Value; } set { IDisposable origValue = null; if (win32Resources.IsValueInitialized) { origValue = win32Resources.Value; if (origValue == value) return; } win32Resources.Value = value; if (origValue != null) origValue.Dispose(); } } /// /// Constructor /// /// The PE stream creator /// Image layout /// Verify PE file data public PEImage(IImageStreamCreator imageStreamCreator, ImageLayout imageLayout, bool verify) { try { this.imageStreamCreator = imageStreamCreator; this.peType = ConvertImageLayout(imageLayout); ResetReader(); this.peInfo = new PEInfo(imageStream, verify); Initialize(); } catch { Dispose(); throw; } } void Initialize() { win32Resources.ReadOriginalValue = () => { var dataDir = peInfo.ImageNTHeaders.OptionalHeader.DataDirectories[2]; if (dataDir.VirtualAddress == 0 || dataDir.Size == 0) return null; return new Win32ResourcesPE(this); }; #if THREAD_SAFE win32Resources.Lock = theLock; #endif } static IPEType ConvertImageLayout(ImageLayout imageLayout) { switch (imageLayout) { case ImageLayout.File: return FileLayout; case ImageLayout.Memory: return MemoryLayout; default: throw new ArgumentException("imageLayout"); } } /// /// Constructor /// /// Name of the file /// true if we should map it as an executable /// Verify PE file data public PEImage(string fileName, bool mapAsImage, bool verify) : this(ImageStreamCreator.Create(fileName, mapAsImage), mapAsImage ? ImageLayout.Memory : ImageLayout.File, verify) { try { if (mapAsImage && imageStreamCreator is MemoryMappedFileStreamCreator) { ((MemoryMappedFileStreamCreator)imageStreamCreator).Length = peInfo.GetImageSize(); ResetReader(); } } catch { Dispose(); throw; } } /// /// Constructor /// /// Name of the file /// Verify PE file data public PEImage(string fileName, bool verify) : this(fileName, USE_MEMORY_LAYOUT_WITH_MAPPED_FILES, verify) { } /// /// Constructor /// /// Name of the file public PEImage(string fileName) : this(fileName, true) { } /// /// Constructor /// /// The PE file data /// Filename or null /// Image layout /// Verify PE file data public PEImage(byte[] data, string filename, ImageLayout imageLayout, bool verify) : this(new MemoryStreamCreator(data) { FileName = filename }, imageLayout, verify) { } /// /// Constructor /// /// The PE file data /// Image layout /// Verify PE file data public PEImage(byte[] data, ImageLayout imageLayout, bool verify) : this(data, null, imageLayout, verify) { } /// /// Constructor /// /// The PE file data /// Verify PE file data public PEImage(byte[] data, bool verify) : this(data, null, ImageLayout.File, verify) { } /// /// Constructor /// /// The PE file data /// Filename or null /// Verify PE file data public PEImage(byte[] data, string filename, bool verify) : this(data, filename, ImageLayout.File, verify) { } /// /// Constructor /// /// The PE file data public PEImage(byte[] data) : this(data, null, true) { } /// /// Constructor /// /// The PE file data /// Filename or null public PEImage(byte[] data, string filename) : this(data, filename, true) { } /// /// Constructor /// /// Address of PE image /// Length of PE image /// Image layout /// Verify PE file data public PEImage(IntPtr baseAddr, long length, ImageLayout imageLayout, bool verify) : this(new UnmanagedMemoryStreamCreator(baseAddr, length), imageLayout, verify) { } /// /// Constructor /// /// Address of PE image /// Length of PE image /// Verify PE file data public PEImage(IntPtr baseAddr, long length, bool verify) : this(baseAddr, length, ImageLayout.Memory, verify) { } /// /// Constructor /// /// Address of PE image /// Length of PE image public PEImage(IntPtr baseAddr, long length) : this(baseAddr, length, true) { } /// /// Constructor /// /// Address of PE image /// Image layout /// Verify PE file data public PEImage(IntPtr baseAddr, ImageLayout imageLayout, bool verify) : this(new UnmanagedMemoryStreamCreator(baseAddr, 0x10000), imageLayout, verify) { try { ((UnmanagedMemoryStreamCreator)imageStreamCreator).Length = peInfo.GetImageSize(); ResetReader(); } catch { Dispose(); throw; } } /// /// Constructor /// /// Address of PE image /// Verify PE file data public PEImage(IntPtr baseAddr, bool verify) : this(baseAddr, ImageLayout.Memory, verify) { } /// /// Constructor /// /// Address of PE image public PEImage(IntPtr baseAddr) : this(baseAddr, true) { } void ResetReader() { if (imageStream != null) { imageStream.Dispose(); imageStream = null; } imageStream = imageStreamCreator.CreateFull(); } /// public RVA ToRVA(FileOffset offset) { return peType.ToRVA(peInfo, offset); } /// public FileOffset ToFileOffset(RVA rva) { return peType.ToFileOffset(peInfo, rva); } /// public void Dispose() { IDisposable id; if (win32Resources.IsValueInitialized && (id = win32Resources.Value) != null) id.Dispose(); if ((id = imageStream) != null) id.Dispose(); if ((id = imageStreamCreator) != null) id.Dispose(); win32Resources.Value = null; imageStream = null; imageStreamCreator = null; peType = null; peInfo = null; } /// public IImageStream CreateStream(FileOffset offset) { if ((long)offset > imageStreamCreator.Length) throw new ArgumentOutOfRangeException("offset"); long length = imageStreamCreator.Length - (long)offset; return CreateStream(offset, length); } /// public IImageStream CreateStream(FileOffset offset, long length) { return imageStreamCreator.Create(offset, length); } /// public IImageStream CreateFullStream() { return imageStreamCreator.CreateFull(); } /// public void UnsafeDisableMemoryMappedIO() { var creator = imageStreamCreator as MemoryMappedFileStreamCreator; if (creator != null) creator.UnsafeDisableMemoryMappedIO(); } /// public bool IsMemoryMappedIO { get { var creator = imageStreamCreator as MemoryMappedFileStreamCreator; return creator == null ? false : creator.IsMemoryMappedIO; } } ImageDebugDirectory[] ReadImageDebugDirectories() { try { if (6 >= ImageNTHeaders.OptionalHeader.DataDirectories.Length) return emptyImageDebugDirectories; var dataDir = ImageNTHeaders.OptionalHeader.DataDirectories[6]; if (dataDir.VirtualAddress == 0) return emptyImageDebugDirectories; using (var reader = imageStream.Clone()) { if (dataDir.Size > reader.Length) return emptyImageDebugDirectories; int count = (int)(dataDir.Size / 0x1C); if (count == 0) return emptyImageDebugDirectories; reader.Position = (long)ToFileOffset(dataDir.VirtualAddress); if (reader.Position + dataDir.Size > reader.Length) return emptyImageDebugDirectories; var res = new ImageDebugDirectory[count]; for (int i = 0; i < res.Length; i++) res[i] = new ImageDebugDirectory(reader, true); return res; } } catch (IOException) { } return emptyImageDebugDirectories; } static readonly ImageDebugDirectory[] emptyImageDebugDirectories = new ImageDebugDirectory[0]; } } dnlib-2.1_VS2010/src/PE/PEInfo.cs000066400000000000000000000106111325033663500161260ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; namespace dnlib.PE { /// /// Reads all PE sections from a PE stream /// sealed class PEInfo { readonly ImageDosHeader imageDosHeader; readonly ImageNTHeaders imageNTHeaders; readonly ImageSectionHeader[] imageSectionHeaders; /// /// Returns the DOS header /// public ImageDosHeader ImageDosHeader { get { return imageDosHeader; } } /// /// Returns the NT headers /// public ImageNTHeaders ImageNTHeaders { get { return imageNTHeaders; } } /// /// Returns the section headers /// public ImageSectionHeader[] ImageSectionHeaders { get { return imageSectionHeaders; } } /// /// Constructor /// /// PE file reader pointing to the start of this section /// Verify sections /// Thrown if verification fails public PEInfo(IImageStream reader, bool verify) { reader.Position = 0; this.imageDosHeader = new ImageDosHeader(reader, verify); if (verify && this.imageDosHeader.NTHeadersOffset == 0) throw new BadImageFormatException("Invalid NT headers offset"); reader.Position = this.imageDosHeader.NTHeadersOffset; this.imageNTHeaders = new ImageNTHeaders(reader, verify); reader.Position = (long)this.imageNTHeaders.OptionalHeader.StartOffset + this.imageNTHeaders.FileHeader.SizeOfOptionalHeader; this.imageSectionHeaders = new ImageSectionHeader[this.imageNTHeaders.FileHeader.NumberOfSections]; for (int i = 0; i < this.imageSectionHeaders.Length; i++) this.imageSectionHeaders[i] = new ImageSectionHeader(reader, verify); } /// /// Returns the first that has data at file offset /// /// /// The file offset /// public ImageSectionHeader ToImageSectionHeader(FileOffset offset) { foreach (var section in imageSectionHeaders) { if ((long)offset >= section.PointerToRawData && (long)offset < section.PointerToRawData + section.SizeOfRawData) return section; } return null; } /// /// Returns the first that has data at RVA /// /// /// The RVA /// public ImageSectionHeader ToImageSectionHeader(RVA rva) { foreach (var section in imageSectionHeaders) { if (rva >= section.VirtualAddress && rva < section.VirtualAddress + Math.Max(section.VirtualSize, section.SizeOfRawData)) return section; } return null; } /// /// Converts a to an /// /// The file offset to convert /// The RVA public RVA ToRVA(FileOffset offset) { var section = ToImageSectionHeader(offset); if (section != null) return (uint)(offset - section.PointerToRawData) + section.VirtualAddress; return (RVA)offset; } /// /// Converts an to a /// /// The RVA to convert /// The file offset public FileOffset ToFileOffset(RVA rva) { var section = ToImageSectionHeader(rva); if (section != null) return (FileOffset)((long)(rva - section.VirtualAddress) + section.PointerToRawData); return (FileOffset)rva; } static ulong AlignUp(ulong val, uint alignment) { return (val + alignment - 1) & ~(ulong)(alignment - 1); } /// /// Returns size of image rounded up to /// /// It calculates the size itself, and does not return /// Size of image in bytes public long GetImageSize() { var optHdr = ImageNTHeaders.OptionalHeader; uint alignment = optHdr.SectionAlignment; ulong len = AlignUp(optHdr.SizeOfHeaders, alignment); foreach (var section in imageSectionHeaders) { ulong len2 = AlignUp((ulong)section.VirtualAddress + Math.Max(section.VirtualSize, section.SizeOfRawData), alignment); if (len2 > len) len = len2; } return (long)len; } } } dnlib-2.1_VS2010/src/PE/RVA.cs000066400000000000000000000013371325033663500154430ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.PE { /// /// Represents an RVA (relative virtual address) /// public enum RVA : uint { } partial class PEExtensions { /// /// Align up /// /// this /// Alignment public static RVA AlignUp(this RVA rva, uint alignment) { return (RVA)(((uint)rva + alignment - 1) & ~(alignment - 1)); } /// /// Align up /// /// this /// Alignment public static RVA AlignUp(this RVA rva, int alignment) { return (RVA)(((uint)rva + alignment - 1) & ~(alignment - 1)); } } } dnlib-2.1_VS2010/src/PE/Subsystem.cs000066400000000000000000000020311325033663500170010ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.PE { /// /// IMAGE_OPTIONAL_HEADER.Subsystem /// public enum Subsystem : ushort { /// Unknown subsystem. Unknown = 0, /// Image doesn't require a subsystem. Native = 1, /// Image runs in the Windows GUI subsystem. WindowsGui = 2, /// Image runs in the Windows character subsystem. WindowsCui = 3, /// image runs in the OS/2 character subsystem. Os2Cui = 5, /// image runs in the Posix character subsystem. PosixCui = 7, /// image is a native Win9x driver. NativeWindows = 8, /// Image runs in the Windows CE subsystem. WindowsCeGui = 9, /// EfiApplication = 10, /// EfiBootServiceDriver = 11, /// EfiRuntimeDriver = 12, /// EfiRom = 13, /// Xbox = 14, /// WindowsBootApplication = 16, } } dnlib-2.1_VS2010/src/Properties/000077500000000000000000000000001325033663500163105ustar00rootroot00000000000000dnlib-2.1_VS2010/src/Properties/AssemblyInfo.cs000066400000000000000000000012031325033663500212260ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Reflection; using System.Runtime.InteropServices; #if THREAD_SAFE [assembly: AssemblyTitle("dnlib (thread safe)")] #else [assembly: AssemblyTitle("dnlib")] #endif [assembly: AssemblyDescription(".NET assembly reader/writer")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("dnlib")] [assembly: AssemblyCopyright("Copyright (C) 2012-2018 de4dot@gmail.com")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] [assembly: AssemblyVersion("2.1.0.0")] [assembly: AssemblyFileVersion("2.1.0.0")] dnlib-2.1_VS2010/src/Settings.cs000066400000000000000000000006141325033663500163040ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib { /// /// dnlib settings /// public static class Settings { /// /// true if dnlib is thread safe. (THREAD_SAFE was defined during compilation) /// public static bool IsThreadSafe { get { #if THREAD_SAFE return true; #else return false; #endif } } } } dnlib-2.1_VS2010/src/Threading/000077500000000000000000000000001325033663500160615ustar00rootroot00000000000000dnlib-2.1_VS2010/src/Threading/Extensions.cs000066400000000000000000000002601325033663500205450ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.Threading { /// /// Extension methods /// public static partial class Extensions { } } dnlib-2.1_VS2010/src/Threading/ICancellationToken.cs000066400000000000000000000005501325033663500221160ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.Threading { /// /// Cancellation token interface /// public interface ICancellationToken { /// /// Throws a if the operation should be canceled /// void ThrowIfCancellationRequested(); } } dnlib-2.1_VS2010/src/Threading/IThreadSafeList.cs000066400000000000000000001007321325033663500213660ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.Threading.Collections { #if THREAD_SAFE /// /// Thread-safe interface /// /// List type public interface IList : System.Collections.Generic.IList { /// /// Must only be called when the list lock is held. Gets the index of /// /// Item /// Index of or -1 if it's not present in the list /// int IndexOf_NoLock(T item); /// /// Must only be called when the list lock is held. Inserts at index /// /// /// Index /// Item to insert /// void Insert_NoLock(int index, T item); /// /// Must only be called when the list lock is held. Removes the item at index /// /// /// /// void RemoveAt_NoLock(int index); /// /// Must only be called when the list lock is held. Returns the value at a specified index. /// /// Index /// Value /// T Get_NoLock(int index); /// /// Must only be called when the list lock is held. Writes to the list at a specified index. /// /// Index /// Value /// void Set_NoLock(int index, T value); /// /// Must only be called when the list lock is held. Adds a new element to the end of the /// list. /// /// Item /// void Add_NoLock(T item); /// /// Must only be called when the list lock is held. Clears the list. /// /// void Clear_NoLock(); /// /// Must only be called when the list lock is held. Checks whether /// exists in the list. /// /// Item /// true if exists in the list, else false /// bool Contains_NoLock(T item); /// /// Must only be called when the list lock is held. Copies the list to an array. /// /// Destination array /// Destination array index /// void CopyTo_NoLock(T[] array, int arrayIndex); /// /// Must only be called when the list lock is held. Returns the size of the list. /// /// int Count_NoLock { get; } /// /// Must only be called when the list lock is held. Returns true if the list is /// read-only, false if it's writable. /// /// bool IsReadOnly_NoLock { get; } /// /// Must only be called when the list lock is held. Removes from the /// list. /// /// Item /// true if was removed, false if /// was never inserted in the list. /// bool Remove_NoLock(T item); /// /// Must only be called when the list lock is held. Gets the enumerator. /// /// A new enumerator instance /// IEnumerator GetEnumerator_NoLock(); /// /// Locks the list and then calls . /// must only call *_NoLock() methods. The list is unlocked once this method returns. /// /// Argument type /// Return type /// Passed to /// Handler that should execute when the lock is held /// The value returns /// /// /// /// /// /// /// /// /// /// /// /// /// TRetType ExecuteLocked(TArgType arg, ExecuteLockedDelegate handler); } #endif } namespace dnlib.Threading { /// /// Passed to ExecuteLocked() /// /// Type to store in list /// Argument type /// Return type /// A thread-safe list /// The argument /// Any value the user wants to return public delegate TRetType ExecuteLockedDelegate(ThreadSafe.IList tsList, TArgType arg); #if THREAD_SAFE /// /// Called by /// /// Type to store in list /// A thread-safe list /// Index of /// Value at in the list /// false to break out of the iterator loop and return public delegate bool IterateDelegate(ThreadSafe.IList tsList, int index, T value); /// /// Called by /// and /// /// Type to store in list /// A thread-safe list /// Index of /// Value at in the list public delegate void IterateAllDelegate(ThreadSafe.IList tsList, int index, T value); #endif /// /// Called by /// /// Type to store in list /// A list /// Index of /// Value at in the list /// false to break out of the iterator loop and return public delegate bool ListIterateDelegate(IList list, int index, T value); /// /// Called by /// and /// /// Type to store in list /// A list /// Index of /// Value at in the list /// false to break out of the iterator loop and return public delegate void ListIterateAllDelegate(IList list, int index, T value); /// /// Called by /// /// Type stored in enumerable /// Index of /// Value at in the collection /// false to break out of the iterator loop and return public delegate bool EnumerableIterateDelegate(int index, T value); /// /// Called by /// /// Type stored in enumerable /// Index of /// Value at in the collection /// false to break out of the iterator loop and return public delegate void EnumerableIterateAllDelegate(int index, T value); public static partial class Extensions { /// /// Locks the list and then calls . /// must only call *_NoLock() methods. The list is unlocked once this method returns. /// /// List type /// Argument type /// Return type /// A list /// Passed to /// Handler that should execute when the lock is held /// The value returns public static TRetType ExecuteLocked(this ThreadSafe.IList tsList, TArgType arg, ExecuteLockedDelegate handler) { #if THREAD_SAFE return tsList.ExecuteLocked(arg, handler); #else return handler(tsList, arg); #endif } #if THREAD_SAFE /// /// Iterates over elements in and calls /// /// Type to store in list /// A thread-safe list /// Called for each element /// Start index /// End index. -1 means /// true if we should iterate in the reverse order public static void Iterate(this ThreadSafe.IList tsList, int startIndex, int endIndex, bool reverseOrder, IterateDelegate handler) { tsList.ExecuteLocked(null, (tsList2, arg) => { if (reverseOrder) { int i = (endIndex < 0 ? tsList2.Count_NoLock : endIndex) - 1; for (; i >= startIndex; i--) { if (!handler(tsList2, i, tsList2.Get_NoLock(i))) break; } } else { // Count property can change so check it each time in the loop for (int i = startIndex; i < (endIndex < 0 ? tsList2.Count_NoLock : endIndex); i++) { if (!handler(tsList2, i, tsList2.Get_NoLock(i))) break; } } return null; }); } /// /// Iterates over all elements in and calls /// /// Type to store in list /// A thread-safe list /// Called for each element public static void Iterate(this ThreadSafe.IList tsList, IterateDelegate handler) { tsList.Iterate(0, -1, false, handler); } /// /// Iterates over all elements in and calls /// /// Type to store in list /// A thread-safe list /// Called for each element public static void IterateAll(this ThreadSafe.IList tsList, IterateAllDelegate handler) { tsList.Iterate(0, -1, false, (tsList2, index, value) => { handler(tsList2, index, value); return true; }); } /// /// Iterates over all elements in in the reverse order and calls /// /// /// Type to store in list /// A thread-safe list /// Called for each element public static void IterateReverse(this ThreadSafe.IList tsList, IterateDelegate handler) { tsList.Iterate(0, -1, true, handler); } /// /// Iterates over all elements in in the reverse order and calls /// /// /// Type to store in list /// A thread-safe list /// Called for each element public static void IterateAllReverse(this ThreadSafe.IList tsList, IterateAllDelegate handler) { tsList.Iterate(0, -1, true, (tsList2, index, value) => { handler(tsList2, index, value); return true; }); } #endif /// /// Iterates over elements in and calls . /// If implements , only thread safe /// methods are called. /// /// Type to store in list /// A list /// Called for each element /// Start index /// End index. -1 means Count_NoLock /// true if we should iterate in the reverse order public static void Iterate(this IList list, int startIndex, int endIndex, bool reverseOrder, ListIterateDelegate handler) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) tsList.Iterate(startIndex, endIndex, reverseOrder, (tsList2, index, value) => handler(tsList2, index, value)); else { #endif if (reverseOrder) { int i = (endIndex < 0 ? list.Count : endIndex) - 1; for (; i >= startIndex; i--) { if (!handler(list, i, list[i])) break; } } else { // Count property can change so check it each time in the loop for (int i = startIndex; i < (endIndex < 0 ? list.Count : endIndex); i++) { if (!handler(list, i, list[i])) break; } } #if THREAD_SAFE } #endif } /// /// Iterates over all elements in and calls /// . If implements /// , only thread safe methods are called. /// /// Type to store in list /// A list /// Called for each element public static void Iterate(this IList list, ListIterateDelegate handler) { list.Iterate(0, -1, false, handler); } /// /// Iterates over all elements in and calls /// . If implements /// , only thread safe methods are called. /// /// Type to store in list /// A list /// Called for each element public static void IterateAll(this IList list, ListIterateAllDelegate handler) { list.Iterate(0, -1, false, (list2, index, value) => { handler(list2, index, value); return true; }); } /// /// Iterates over all elements in in the reverse order and calls /// . If implements /// , only thread safe methods are called. /// /// Type to store in list /// A list /// Called for each element public static void IterateReverse(this IList list, ListIterateDelegate handler) { list.Iterate(0, -1, true, handler); } /// /// Iterates over all elements in in the reverse order and calls /// . If implements /// , only thread safe methods are called. /// /// Type to store in list /// A list /// Called for each element public static void IterateAllReverse(this IList list, ListIterateAllDelegate handler) { list.Iterate(0, -1, true, (list2, index, value) => { handler(list2, index, value); return true; }); } /// /// Iterates over all elements in and calls /// . If implements /// , only thread safe methods are called. /// /// Type to store in list /// A list /// Called for each element public static void Iterate(this IEnumerable list, EnumerableIterateDelegate handler) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) tsList.Iterate((tsList2, index, value) => handler(index, value)); else { #endif int i = 0; foreach (var value in list) { if (!handler(i, value)) break; i++; } #if THREAD_SAFE } #endif } /// /// Iterates over all elements in and calls /// . If implements /// , only thread safe methods are called. /// /// Type to store in list /// A list /// Called for each element public static void IterateAll(this IEnumerable list, EnumerableIterateAllDelegate handler) { list.Iterate((index, value) => { handler(index, value); return true; }); } /// /// Reads an element from the list. If implements /// , only thread safe methods are called. /// /// Type to store in list /// A list /// Index /// Updated with value /// true if was updated with the element in the /// list or false if was invalid. public static bool Get(this IList list, int index, out T value) { #if THREAD_SAFE try { #endif if ((uint)index < (uint)list.Count) { value = list[index]; return true; } #if THREAD_SAFE } catch (IndexOutOfRangeException) { } catch (ArgumentOutOfRangeException) { } #endif value = default(T); return false; } /// /// Reads an element from the list. If implements /// , only thread safe methods are called. /// /// Type to store in list /// A list /// Index /// Default value if is invalid /// The value in the list or if /// was invalid public static T Get(this IList list, int index, T defaultValue) { T value; return list.Get(index, out value) ? value : defaultValue; } /// /// Writes an element to the list. If implements /// , only thread safe methods are called. /// /// Type to store in list /// A list /// Index /// Value /// true if was written to the list or false /// if was invalid. public static bool Set(this IList list, int index, T value) { #if THREAD_SAFE try { #endif if ((uint)index < (uint)list.Count) { list[index] = value; return true; } #if THREAD_SAFE } catch (IndexOutOfRangeException) { } catch (ArgumentOutOfRangeException) { } #endif return false; } #if THREAD_SAFE /// /// Calls /// /// Type to store in list /// A thread-safe list /// Number of elements in the list public static int Count_NoLock(this ThreadSafe.IList tsList) { return tsList.Count_NoLock; } /// /// Calls /// /// Type to store in list /// A thread-safe list public static bool IsReadOnly_NoLock(this ThreadSafe.IList tsList) { return tsList.IsReadOnly_NoLock; } #endif /// /// Calls the thread-safe IndexOf_NoLock() method if implements /// a thread-safe list interface, else calls setter /// /// Type to store in list /// An /// Item /// Index of public static int IndexOf_NoLock(this IList list, T item) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) return tsList.IndexOf_NoLock(item); else #endif return list.IndexOf(item); } /// /// Calls the thread-safe Insert_NoLock() method if implements /// a thread-safe list interface, else calls setter /// /// Type to store in list /// An /// Index /// Item public static void Insert_NoLock(this IList list, int index, T item) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) tsList.Insert_NoLock(index, item); else #endif list.Insert(index, item); } /// /// Calls the thread-safe RemoveAt_NoLock() method if implements /// a thread-safe list interface, else calls setter /// /// Type to store in list /// An /// Index public static void RemoveAt_NoLock(this IList list, int index) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) tsList.RemoveAt_NoLock(index); else #endif list.RemoveAt(index); } /// /// Calls the thread-safe Get_NoLock() method if implements /// a thread-safe list interface, else calls setter /// /// Type to store in list /// An /// Index /// Value at index public static T Get_NoLock(this IList list, int index) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) return tsList.Get_NoLock(index); else #endif return list[index]; } /// /// Calls the thread-safe Set_NoLock() method if implements /// a thread-safe list interface, else calls setter /// /// Type to store in list /// An /// Index /// Value public static void Set_NoLock(this IList list, int index, T value) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) tsList.Set_NoLock(index, value); else #endif list[index] = value; } /// /// Calls the thread-safe Add_NoLock() method if implements /// a thread-safe list interface, else calls setter /// /// Type to store in list /// An /// Item public static void Add_NoLock(this ICollection list, T item) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) tsList.Add_NoLock(item); else #endif list.Add(item); } /// /// Calls the thread-safe Clear_NoLock() method if implements /// a thread-safe list interface, else calls setter /// /// Type to store in list /// An public static void Clear_NoLock(this ICollection list) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) tsList.Clear_NoLock(); else #endif list.Clear(); } /// /// Calls the thread-safe Contains_NoLock() method if implements /// a thread-safe list interface, else calls setter /// /// Type to store in list /// An /// Item /// true if is in the list, else false public static bool Contains_NoLock(this ICollection list, T item) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) return tsList.Contains_NoLock(item); else #endif return list.Contains(item); } /// /// Calls the thread-safe CopyTo_NoLock() method if implements /// a thread-safe list interface, else calls setter /// /// Type to store in list /// An /// Destination array /// Destination index public static void CopyTo_NoLock(this ICollection list, T[] array, int arrayIndex) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) tsList.CopyTo_NoLock(array, arrayIndex); else #endif list.CopyTo(array, arrayIndex); } /// /// Calls the thread-safe Count_NoLock() method if implements /// a thread-safe list interface, else calls setter /// /// Type to store in list /// An /// Number of elements in the list public static int Count_NoLock(this ICollection list) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) return tsList.Count_NoLock; else #endif return list.Count; } /// /// Calls the thread-safe IsReadOnly_NoLock() method if implements /// a thread-safe list interface, else calls setter /// /// Type to store in list /// An public static bool IsReadOnly_NoLock(this ICollection list) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) return tsList.IsReadOnly_NoLock; else #endif return list.IsReadOnly; } /// /// Calls the thread-safe Remove_NoLock() method if implements /// a thread-safe list interface, else calls setter /// /// Type to store in list /// An /// Item /// true if was removed, else false public static bool Remove_NoLock(this ICollection list, T item) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) return tsList.Remove_NoLock(item); else #endif return list.Remove(item); } /// /// Calls the thread-safe GetEnumerator_NoLock() method if implements /// a thread-safe list interface, else calls setter /// /// Type to store in list /// An /// A new instance public static IEnumerator GetEnumerator_NoLock(this IEnumerable list) { #if THREAD_SAFE var tsList = list as ThreadSafe.IList; if (tsList != null) return tsList.GetEnumerator_NoLock(); else #endif return list.GetEnumerator(); } /// /// Calls to get an /// which is used to iterate over the whole list. Each item is /// then returned to the caller. /// /// Type to store in list /// An /// All items of the list public static IEnumerable GetEnumerable_NoLock(this ICollection list) { using (var enumerator = list.GetEnumerator_NoLock()) { while (enumerator.MoveNext()) yield return enumerator.Current; } } /// /// Iterates over the whole list but doesn't keep the lock. It doesn't use any enumerator /// so no exception can be thrown if another thread modifies the list. /// /// Type to store in list /// A list /// A list enumerable public static IEnumerable GetSafeEnumerable(this IList list) { for (int i = 0; i < list.Count; i++) { T value; #if THREAD_SAFE try { #endif value = list[i]; #if THREAD_SAFE } catch (IndexOutOfRangeException) { break; } catch (ArgumentOutOfRangeException) { break; } #endif yield return value; } } /// /// Iterates over the whole list but doesn't keep the lock. It doesn't use any enumerator /// so no exception can be thrown if another thread modifies the list. /// /// Type to store in list /// A collection /// A list enumerable public static IEnumerable GetSafeEnumerable(this IEnumerable coll) { var list = coll as IList; if (list != null) return GetSafeEnumerable(list); return coll; } } } dnlib-2.1_VS2010/src/Threading/Lock.cs000066400000000000000000000037551325033663500173120ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Runtime.Serialization; using System.Threading; namespace dnlib.Threading { #if THREAD_SAFE [Serializable] class LockException : Exception { public LockException() { } public LockException(string msg) : base(msg) { } protected LockException(SerializationInfo info, StreamingContext context) : base(info, context) { } } /// /// Simple class using and /// and just like ReaderWriterLockSlim it prevents recursive locks. It doesn't support /// multiple readers. A reader lock is the same as a writer lock. /// class Lock { readonly object lockObj; int recurseCount; /// /// Creates a new instance of this class /// /// public static Lock Create() { return new Lock(); } /// /// Constructor /// Lock() { this.lockObj = new object(); this.recurseCount = 0; } /// /// Enter read mode /// public void EnterReadLock() { Monitor.Enter(lockObj); if (recurseCount != 0) { Monitor.Exit(lockObj); throw new LockException("Recursive locks aren't supported"); } recurseCount++; } /// /// Exit read mode /// public void ExitReadLock() { if (recurseCount <= 0) throw new LockException("Too many exit lock method calls"); recurseCount--; Monitor.Exit(lockObj); } /// /// Enter write mode /// public void EnterWriteLock() { Monitor.Enter(lockObj); if (recurseCount != 0) { Monitor.Exit(lockObj); throw new LockException("Recursive locks aren't supported"); } recurseCount--; } /// /// Exit write mode /// public void ExitWriteLock() { if (recurseCount >= 0) throw new LockException("Too many exit lock method calls"); recurseCount++; Monitor.Exit(lockObj); } } #endif } dnlib-2.1_VS2010/src/Threading/ThreadSafeListCreator.cs000066400000000000000000000102171325033663500225730ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Collections.Generic; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.Threading { /// /// Creates thread-safe lists /// public static class ThreadSafeListCreator { /// /// Creates a thread safe /// /// List type /// A new thread-safe list instance public static ThreadSafe.IList Create() { var list = new List(); #if THREAD_SAFE return new ThreadSafeListWrapper(list); #else return list; #endif } /// /// Creates a thread safe /// /// List type /// Value to add to the list /// A new thread-safe list instance public static ThreadSafe.IList Create(T value) { var list = new List() { value }; #if THREAD_SAFE return new ThreadSafeListWrapper(list); #else return list; #endif } /// /// Creates a thread safe /// /// List type /// Value #1 to add to the list /// Value #2 to add to the list /// A new thread-safe list instance public static ThreadSafe.IList Create(T value1, T value2) { var list = new List() { value1, value2 }; #if THREAD_SAFE return new ThreadSafeListWrapper(list); #else return list; #endif } /// /// Creates a thread safe /// /// List type /// Value #1 to add to the list /// Value #2 to add to the list /// Value #3 to add to the list /// A new thread-safe list instance public static ThreadSafe.IList Create(T value1, T value2, T value3) { var list = new List() { value1, value2, value3 }; #if THREAD_SAFE return new ThreadSafeListWrapper(list); #else return list; #endif } /// /// Creates a thread safe /// /// List type /// Values to add to the list /// A new thread-safe list instance public static ThreadSafe.IList Create(params T[] args) { var list = new List(args); #if THREAD_SAFE return new ThreadSafeListWrapper(list); #else return list; #endif } /// /// Creates a thread safe /// /// List type /// List capacity /// A new thread-safe list instance public static ThreadSafe.IList Create(int capacity) { var list = new List(capacity); #if THREAD_SAFE return new ThreadSafeListWrapper(list); #else return list; #endif } /// /// Creates a thread safe /// /// List type /// Values to copy to the new list /// A new thread-safe list instance public static ThreadSafe.IList Create(IEnumerable collection) { var list = new List(collection); #if THREAD_SAFE return new ThreadSafeListWrapper(list); #else return list; #endif } /// /// Makes a list thread-safe by using a thread-safe wrapper list /// /// List type /// The list that should be made thread-safe /// A thread-safe list using as the underlying list public static ThreadSafe.IList MakeThreadSafe(IList list) { #if THREAD_SAFE if (list == null) return null; var tsList = list as ThreadSafe.IList; if (tsList != null) return tsList; return new ThreadSafeListWrapper(list); #else return list; #endif } } } dnlib-2.1_VS2010/src/Threading/ThreadSafeListWrapper.cs000066400000000000000000000111531325033663500226140ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Diagnostics; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.Threading { #if THREAD_SAFE /// /// Protects an from being accessed by multiple threads at the same time /// /// List type [DebuggerDisplay("Count = {Count}")] sealed class ThreadSafeListWrapper : ThreadSafe.IList { [DebuggerBrowsable(DebuggerBrowsableState.Never)] readonly Lock theLock = Lock.Create(); readonly IList list; /// /// Constructor /// /// A list public ThreadSafeListWrapper(IList list) { if (list == null) throw new ArgumentNullException("list"); this.list = list; } /// public int IndexOf(T item) { // We need a write lock since we don't know whether 'list' modifies any internal fields. theLock.EnterWriteLock(); try { return list.IndexOf(item); } finally { theLock.ExitWriteLock(); } } /// public void Insert(int index, T item) { theLock.EnterWriteLock(); try { list.Insert(index, item); } finally { theLock.ExitWriteLock(); } } /// public void RemoveAt(int index) { theLock.EnterWriteLock(); try { list.RemoveAt(index); } finally { theLock.ExitWriteLock(); } } /// public T this[int index] { get { theLock.EnterWriteLock(); try { return list[index]; } finally { theLock.ExitWriteLock(); } } set { theLock.EnterWriteLock(); try { list[index] = value; } finally { theLock.ExitWriteLock(); } } } /// public void Add(T item) { theLock.EnterWriteLock(); try { list.Add(item); } finally { theLock.ExitWriteLock(); } } /// public void Clear() { theLock.EnterWriteLock(); try { list.Clear(); } finally { theLock.ExitWriteLock(); } } /// public bool Contains(T item) { theLock.EnterWriteLock(); try { return list.Contains(item); } finally { theLock.ExitWriteLock(); } } /// public void CopyTo(T[] array, int arrayIndex) { theLock.EnterWriteLock(); try { list.CopyTo(array, arrayIndex); } finally { theLock.ExitWriteLock(); } } /// public int Count { get { theLock.EnterWriteLock(); try { return list.Count; } finally { theLock.ExitWriteLock(); } } } /// public bool IsReadOnly { get { theLock.EnterWriteLock(); try { return list.IsReadOnly; } finally { theLock.ExitWriteLock(); } } } /// public bool Remove(T item) { theLock.EnterWriteLock(); try { return list.Remove(item); } finally { theLock.ExitWriteLock(); } } /// public IEnumerator GetEnumerator() { theLock.EnterWriteLock(); try { return list.GetEnumerator(); } finally { theLock.ExitWriteLock(); } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } /// public int Count_NoLock { get { return list.Count; } } /// public bool IsReadOnly_NoLock { get { return list.IsReadOnly; } } /// public int IndexOf_NoLock(T item) { return list.IndexOf(item); } /// public void Insert_NoLock(int index, T item) { list.Insert(index, item); } /// public void RemoveAt_NoLock(int index) { list.RemoveAt(index); } /// public T Get_NoLock(int index) { return list[index]; } /// public void Set_NoLock(int index, T value) { list[index] = value; } /// public void Add_NoLock(T item) { list.Add(item); } /// public void Clear_NoLock() { list.Clear(); } /// public bool Contains_NoLock(T item) { return list.Contains(item); } /// public void CopyTo_NoLock(T[] array, int arrayIndex) { list.CopyTo(array, arrayIndex); } /// public bool Remove_NoLock(T item) { return list.Remove(item); } /// public IEnumerator GetEnumerator_NoLock() { return list.GetEnumerator(); } /// public TRetType ExecuteLocked(TArgType arg, ExecuteLockedDelegate handler) { theLock.EnterWriteLock(); try { return handler(this, arg); } finally { theLock.ExitWriteLock(); } } } #endif } dnlib-2.1_VS2010/src/Utils/000077500000000000000000000000001325033663500152545ustar00rootroot00000000000000dnlib-2.1_VS2010/src/Utils/Extensions.cs000066400000000000000000000002511325033663500177400ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.Utils { /// /// Extension methods /// public static partial class Extensions { } } dnlib-2.1_VS2010/src/Utils/ILazyList.cs000066400000000000000000000036431325033663500174750ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.Utils { /// /// Interface to access a lazily initialized list /// /// Type to store in list public interface ILazyList : ThreadSafe.IList { /// /// Checks whether an element at has been initialized. /// /// Index of element /// true if the element has been initialized, false otherwise bool IsInitialized(int index); /// /// Checks whether an element at has been initialized. /// /// Index of element /// true if the element has been initialized, false otherwise bool IsInitialized_NoLock(int index); /// /// Gets all initialized elements /// /// true if the list should be cleared before returning, /// false if the list should not cleared. List GetInitializedElements(bool clearList); } public static partial class Extensions { /// /// Disposes all initialized elements /// /// Element type /// this public static void DisposeAll(this ILazyList list) where TValue : IDisposable { list.ExecuteLocked(null, (tsList, arg) => { for (int i = 0; i < list.Count_NoLock(); i++) { if (list.IsInitialized_NoLock(i)) { var elem = list.Get_NoLock(i); if (elem != null) elem.Dispose(); } } return null; }); } } } dnlib-2.1_VS2010/src/Utils/LazyList.cs000066400000000000000000000342611325033663500173640ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using dnlib.Threading; namespace dnlib.Utils { /// /// Gets notified of list events /// /// List value public interface IListListener { /// /// Called before a new value is lazily added to the list. /// /// If you must access this list, you can only call _NoLock() methods /// since a write lock is now held by this thread. /// Index where the value will be added /// Value that will be added to the list. It can be modified by /// the callee. void OnLazyAdd(int index, ref TListValue value); /// /// Called before a new value is added to the list. /// /// If you must access this list, you can only call _NoLock() methods /// since a write lock is now held by this thread. /// Index where the value will be added /// Value that will be added to the list void OnAdd(int index, TListValue value); /// /// Called before a value is removed from the list. If all elements are removed, /// is called, and this method is not called. /// /// If you must access this list, you can only call _NoLock() methods /// since a write lock is now held by this thread. /// Index of value /// The value that will be removed void OnRemove(int index, TListValue value); /// /// Called after the list has been resized (eg. an element has been added/removed). It's not /// called when an element is replaced. /// /// If you must access this list, you can only call _NoLock() methods /// since a write lock is now held by this thread. /// Index where the change occurred. void OnResize(int index); /// /// Called before the whole list is cleared. /// /// If you must access this list, you can only call _NoLock() methods /// since a write lock is now held by this thread. void OnClear(); } /// /// Implements a that is lazily initialized /// /// Type to store in list [DebuggerDisplay("Count = {Count}")] public class LazyList : ILazyList where TValue : class { [DebuggerBrowsable(DebuggerBrowsableState.Never)] readonly object context; [DebuggerBrowsable(DebuggerBrowsableState.Never)] readonly MFunc readOriginalValue; [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] readonly List list; [DebuggerBrowsable(DebuggerBrowsableState.Never)] int id = 0; [DebuggerBrowsable(DebuggerBrowsableState.Never)] readonly IListListener listener; #if THREAD_SAFE [DebuggerBrowsable(DebuggerBrowsableState.Never)] readonly Lock theLock = Lock.Create(); #endif /// /// Stores a simple value /// class Element { protected TValue value; /// /// true if it has been initialized, false otherwise /// public virtual bool IsInitialized_NoLock { get { return true; } } /// /// Default constructor /// protected Element() { } /// /// Constructor that should be used when new elements are inserted into /// /// User data public Element(TValue data) { this.value = data; } /// /// Gets the value /// /// Index in the list public virtual TValue GetValue_NoLock(int index) { return value; } /// /// Sets the value /// /// Index in the list /// New value public virtual void SetValue_NoLock(int index, TValue value) { this.value = value; } /// public override string ToString() { return value == null ? string.Empty : value.ToString(); } } /// /// Stores data and keeps track of the original index and whether the data has been /// initialized or not. /// sealed class LazyElement : Element { internal readonly uint origIndex; LazyList lazyList; /// public override bool IsInitialized_NoLock { get { return lazyList == null; } } /// public override TValue GetValue_NoLock(int index) { if (lazyList != null) { value = lazyList.ReadOriginalValue_NoLock(index, origIndex); lazyList = null; } return value; } /// public override void SetValue_NoLock(int index, TValue value) { this.value = value; lazyList = null; } /// /// Constructor that should only be called when is initialized. /// /// Original index of this element /// LazyList instance public LazyElement(int origIndex, LazyList lazyList) { this.origIndex = (uint)origIndex; this.lazyList = lazyList; } /// public override string ToString() { if (lazyList != null) { value = lazyList.ReadOriginalValue_NoLock(this); lazyList = null; } return value == null ? string.Empty : value.ToString(); } } /// [DebuggerBrowsableAttribute(DebuggerBrowsableState.Never)] public int Count { get { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return Count_NoLock; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } } /// [DebuggerBrowsableAttribute(DebuggerBrowsableState.Never)] public int Count_NoLock { get { return list.Count; } } /// [DebuggerBrowsableAttribute(DebuggerBrowsableState.Never)] public bool IsReadOnly { get { return false; } } /// [DebuggerBrowsableAttribute(DebuggerBrowsableState.Never)] public bool IsReadOnly_NoLock { get { return false; } } /// public TValue this[int index] { get { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif return Get_NoLock(index); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } set { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif Set_NoLock(index, value); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } } /// public TValue Get_NoLock(int index) { return list[index].GetValue_NoLock(index); } /// public void Set_NoLock(int index, TValue value) { if (listener != null) { listener.OnRemove(index, list[index].GetValue_NoLock(index)); listener.OnAdd(index, value); } list[index].SetValue_NoLock(index, value); id++; } /// /// Default constructor /// public LazyList() : this(null) { } /// /// Constructor /// /// List listener public LazyList(IListListener listener) { this.listener = listener; this.list = new List(); } /// /// Constructor /// /// Initial length of the list /// Context passed to /// Delegate instance that returns original values public LazyList(int length, object context, MFunc readOriginalValue) : this(length, null, context, readOriginalValue) { } /// /// Constructor /// /// Initial length of the list /// List listener /// Context passed to /// Delegate instance that returns original values public LazyList(int length, IListListener listener, object context, MFunc readOriginalValue) { this.listener = listener; this.context = context; this.readOriginalValue = readOriginalValue; this.list = new List(length); for (int i = 0; i < length; i++) list.Add(new LazyElement(i, this)); } TValue ReadOriginalValue_NoLock(LazyElement elem) { return ReadOriginalValue_NoLock(list.IndexOf(elem), elem.origIndex); } TValue ReadOriginalValue_NoLock(int index, uint origIndex) { var newValue = readOriginalValue(context, origIndex); if (listener != null) listener.OnLazyAdd(index, ref newValue); return newValue; } /// public int IndexOf(TValue item) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif return IndexOf_NoLock(item); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// public int IndexOf_NoLock(TValue item) { for (int i = 0; i < list.Count; i++) { if (list[i].GetValue_NoLock(i) == item) return i; } return -1; } /// public void Insert(int index, TValue item) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif Insert_NoLock(index, item); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// public void Insert_NoLock(int index, TValue item) { if (listener != null) listener.OnAdd(index, item); list.Insert(index, new Element(item)); if (listener != null) listener.OnResize(index); id++; } /// public void RemoveAt(int index) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif RemoveAt_NoLock(index); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// public void RemoveAt_NoLock(int index) { if (listener != null) listener.OnRemove(index, list[index].GetValue_NoLock(index)); list.RemoveAt(index); if (listener != null) listener.OnResize(index); id++; } /// public void Add(TValue item) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif Add_NoLock(item); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// public void Add_NoLock(TValue item) { int index = list.Count; if (listener != null) listener.OnAdd(index, item); list.Add(new Element(item)); if (listener != null) listener.OnResize(index); id++; } /// public void Clear() { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif Clear_NoLock(); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// public void Clear_NoLock() { if (listener != null) listener.OnClear(); list.Clear(); if (listener != null) listener.OnResize(0); id++; } /// public bool Contains(TValue item) { return IndexOf(item) >= 0; } /// public bool Contains_NoLock(TValue item) { return IndexOf_NoLock(item) >= 0; } /// public void CopyTo(TValue[] array, int arrayIndex) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif CopyTo_NoLock(array, arrayIndex); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// public void CopyTo_NoLock(TValue[] array, int arrayIndex) { for (int i = 0; i < list.Count; i++) array[arrayIndex + i] = list[i].GetValue_NoLock(i); } /// public bool Remove(TValue item) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif return Remove_NoLock(item); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } /// public bool Remove_NoLock(TValue item) { int index = IndexOf_NoLock(item); if (index < 0) return false; RemoveAt_NoLock(index); return true; } /// public bool IsInitialized(int index) { #if THREAD_SAFE theLock.EnterReadLock(); try { #endif return IsInitialized_NoLock(index); #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif } /// public bool IsInitialized_NoLock(int index) { if ((uint)index >= (uint)list.Count) return false; return list[index].IsInitialized_NoLock; } /// public IEnumerator GetEnumerator() { int id2; #if THREAD_SAFE theLock.EnterReadLock(); try { #endif id2 = id; #if THREAD_SAFE } finally { theLock.ExitReadLock(); } #endif for (int i = 0; ; i++) { TValue value; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (id != id2) throw new InvalidOperationException("List was modified"); if (i >= list.Count) break; value = list[i].GetValue_NoLock(i); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif yield return value; } } /// public IEnumerator GetEnumerator_NoLock() { int id2 = id; for (int i = 0; i < list.Count; i++) { if (id != id2) throw new InvalidOperationException("List was modified"); yield return list[i].GetValue_NoLock(i); } } /// public List GetInitializedElements(bool clearList) { List newList; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif newList = new List(list.Count); int id2 = id; for (int i = 0; i < list.Count; i++) { if (id != id2) throw new InvalidOperationException("List was modified"); var elem = list[i]; if (!elem.IsInitialized_NoLock) continue; newList.Add(elem.GetValue_NoLock(i)); } if (clearList) Clear_NoLock(); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif return newList; } /// IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #if THREAD_SAFE /// public TRetType ExecuteLocked(TArgType arg, ExecuteLockedDelegate handler) { theLock.EnterWriteLock(); try { return handler(this, arg); } finally { theLock.ExitWriteLock(); } } #endif } } dnlib-2.1_VS2010/src/Utils/MFunc.cs000066400000000000000000000006531325033663500166170ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.Utils { delegate T MFunc(); delegate U MFunc(T t); /// /// Same as Func delegate /// /// /// /// /// /// /// public delegate V MFunc(T t, U u); } dnlib-2.1_VS2010/src/Utils/SimpleLazyList.cs000066400000000000000000000067721325033663500205440ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Diagnostics; using System.Threading; using dnlib.DotNet; namespace dnlib.Utils { /// /// A readonly list that gets initialized lazily /// /// Any class type [DebuggerDisplay("Count = {Length}")] sealed class SimpleLazyList where T : class { [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] readonly T[] elements; [DebuggerBrowsable(DebuggerBrowsableState.Never)] readonly MFunc readElementByRID; [DebuggerBrowsable(DebuggerBrowsableState.Never)] readonly uint length; /// /// Gets the length of this list /// public uint Length { get { return length; } } /// /// Access the list /// /// Index /// The element or null if is invalid public T this[uint index] { get { if (index >= length) return null; if (elements[index] == null) Interlocked.CompareExchange(ref elements[index], readElementByRID(index + 1), null); return elements[index]; } } /// /// Constructor /// /// Length of the list /// Delegate instance that lazily reads an element. It might /// be called more than once for each rid in rare cases. It must never return /// null. public SimpleLazyList(uint length, MFunc readElementByRID) { this.length = length; this.readElementByRID = readElementByRID; this.elements = new T[length]; } } /// /// A readonly list that gets initialized lazily /// /// Any class type [DebuggerDisplay("Count = {Length}")] sealed class SimpleLazyList2 where T : class, IContainsGenericParameter { [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] readonly T[] elements; [DebuggerBrowsable(DebuggerBrowsableState.Never)] readonly MFunc readElementByRID; [DebuggerBrowsable(DebuggerBrowsableState.Never)] readonly uint length; /// /// Gets the length of this list /// public uint Length { get { return length; } } /// /// Access the list /// /// Index /// Generic parameter context /// The element or null if is invalid public T this[uint index, GenericParamContext gpContext] { get { if (index >= length) return null; if (elements[index] == null) { var elem = readElementByRID(index + 1, gpContext); // Don't cache it if it contains GPs since each GP could hold a reference // to the type/method context. These GPs can't be shared. if (elem.ContainsGenericParameter) return elem; Interlocked.CompareExchange(ref elements[index], elem, null); } return elements[index]; } } /// /// Constructor /// /// Length of the list /// Delegate instance that lazily reads an element. It might /// be called more than once for each rid. It must never return null. public SimpleLazyList2(uint length, MFunc readElementByRID) { this.length = length; this.readElementByRID = readElementByRID; this.elements = new T[length]; } } } dnlib-2.1_VS2010/src/Utils/UserValue.cs000066400000000000000000000044731325033663500175260ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System.Diagnostics; using dnlib.Threading; namespace dnlib.Utils { /// /// Lazily returns the original value if the user hasn't overwritten the value /// /// Value type [DebuggerDisplay("{value}")] struct UserValue { #if THREAD_SAFE Lock theLock; #endif MFunc readOriginalValue; TValue value; bool isUserValue; bool isValueInitialized; #if THREAD_SAFE /// /// Sets the lock that protects the data /// public Lock Lock { set { theLock = value; } } #endif /// /// Set a delegate instance that will return the original value /// public MFunc ReadOriginalValue { set { readOriginalValue = value; } } /// /// Gets/sets the value /// /// The getter returns the original value if the value hasn't been initialized. public TValue Value { get { #if THREAD_SAFE if (theLock != null) theLock.EnterWriteLock(); try { #endif if (!isValueInitialized) { value = readOriginalValue(); readOriginalValue = null; isValueInitialized = true; } return value; #if THREAD_SAFE } finally { if (theLock != null) theLock.ExitWriteLock(); } #endif } set { #if THREAD_SAFE if (theLock != null) theLock.EnterWriteLock(); try { #endif this.value = value; readOriginalValue = null; isUserValue = true; isValueInitialized = true; #if THREAD_SAFE } finally { if (theLock != null) theLock.ExitWriteLock(); } #endif } } /// /// Returns true if the value has been initialized /// public bool IsValueInitialized { #if THREAD_SAFE get { if (theLock != null) theLock.EnterReadLock(); try { return isValueInitialized; } finally { if (theLock != null) theLock.ExitReadLock(); } } #else get { return isValueInitialized; } #endif } /// /// Returns true if the value was set by the user /// public bool IsUserValue { #if THREAD_SAFE get { if (theLock != null) theLock.EnterReadLock(); try { return isUserValue; } finally { if (theLock != null) theLock.ExitReadLock(); } } #else get { return isUserValue; } #endif } } } dnlib-2.1_VS2010/src/W32Resources/000077500000000000000000000000001325033663500164225ustar00rootroot00000000000000dnlib-2.1_VS2010/src/W32Resources/ResourceData.cs000066400000000000000000000042261325033663500213360ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.IO; using System.Threading; using dnlib.IO; namespace dnlib.W32Resources { /// /// A resource blob /// public sealed class ResourceData : ResourceDirectoryEntry, IDisposable { IBinaryReader reader; uint codePage; uint reserved; /// /// Gets/sets the data reader. This instance owns the reader. /// public IBinaryReader Data { get { return reader; } set { var oldValue = Interlocked.Exchange(ref reader, value); if (oldValue != value && oldValue != null) oldValue.Dispose(); } } /// /// Gets/sets the code page /// public uint CodePage { get { return codePage; } set { codePage = value; } } /// /// Gets/sets the reserved field /// public uint Reserved { get { return reserved; } set { reserved = value; } } /// /// Constructor /// /// Name public ResourceData(ResourceName name) : base(name) { } /// /// Constructor /// /// Raw data. This instance owns this reader. /// Name public ResourceData(ResourceName name, IBinaryReader reader) : base(name) { this.reader = reader; } /// /// Constructor /// /// Raw data. This instance owns this reader. /// Name /// Code page /// Reserved value public ResourceData(ResourceName name, IBinaryReader reader, uint codePage, uint reserved) : base(name) { this.reader = reader; this.codePage = codePage; this.reserved = reserved; } /// /// Gets the data as a . It shares the file position with /// public Stream ToDataStream() { return Data.CreateStream(); } /// public void Dispose() { var oldValue = Interlocked.Exchange(ref reader, null); if (oldValue != null) oldValue.Dispose(); } } } dnlib-2.1_VS2010/src/W32Resources/ResourceDirectory.cs000066400000000000000000000220111325033663500224210ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Collections.Generic; using System.Text; using dnlib.Utils; using dnlib.IO; using dnlib.PE; using dnlib.Threading; #if THREAD_SAFE using ThreadSafe = dnlib.Threading.Collections; #else using ThreadSafe = System.Collections.Generic; #endif namespace dnlib.W32Resources { /// /// A Win32 resource directory (see IMAGE_RESOURCE_DIRECTORY in the Windows SDK) /// public abstract class ResourceDirectory : ResourceDirectoryEntry, IDisposable { /// See protected uint characteristics; /// See protected uint timeDateStamp; /// See protected ushort majorVersion; /// See protected ushort minorVersion; /// See protected ILazyList directories; /// See protected ILazyList data; /// /// Gets/sets the characteristics /// public uint Characteristics { get { return characteristics; } set { characteristics = value; } } /// /// Gets/sets the time date stamp /// public uint TimeDateStamp { get { return timeDateStamp; } set { timeDateStamp = value; } } /// /// Gets/sets the major version number /// public ushort MajorVersion { get { return majorVersion; } set { majorVersion = value; } } /// /// Gets/sets the minor version number /// public ushort MinorVersion { get { return minorVersion; } set { minorVersion = value; } } /// /// Gets all directory entries /// public ThreadSafe.IList Directories { get { return directories; } } /// /// Gets all resource data /// public ThreadSafe.IList Data { get { return data; } } /// /// Constructor /// /// Name protected ResourceDirectory(ResourceName name) : base(name) { } /// /// Finds a by name /// /// Name /// A or null if it wasn't found public ResourceDirectory FindDirectory(ResourceName name) { foreach (var dir in directories.GetSafeEnumerable()) { if (dir.Name == name) return dir; } return null; } /// /// Finds a by name /// /// Name /// A or null if it wasn't found public ResourceData FindData(ResourceName name) { foreach (var d in data.GetSafeEnumerable()) { if (d.Name == name) return d; } return null; } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose method /// /// true if called by protected virtual void Dispose(bool disposing) { if (!disposing) return; directories.DisposeAll(); data.DisposeAll(); directories = null; data = null; } } /// /// A Win32 resource directory created by the user /// public class ResourceDirectoryUser : ResourceDirectory { /// /// Constructor /// /// Name public ResourceDirectoryUser(ResourceName name) : base(name) { this.directories = new LazyList(); this.data = new LazyList(); } } /// /// A Win32 resource directory created from a PE file /// public sealed class ResourceDirectoryPE : ResourceDirectory { /// /// To make sure we don't get stuck in an infinite loop, don't allow more than this /// many sub directories. /// const uint MAX_DIR_DEPTH = 10; /// Owner readonly Win32ResourcesPE resources; /// Directory depth. When creating more 's, /// the instances get this value + 1 uint depth; /// /// Info about all 's we haven't created yet /// List dataInfos; /// /// Info about all 's we haven't created yet /// List dirInfos; struct EntryInfo { public readonly ResourceName name; /// Offset of resource directory / data public readonly uint offset; public EntryInfo(ResourceName name, uint offset) { this.name = name; this.offset = offset; } public override string ToString() { return string.Format("{0:X8} {1}", offset, name); } } /// /// Constructor /// /// Starts from 0. If it's big enough, we'll stop reading more data. /// Name /// Resources /// Reader positioned at the start of this resource directory public ResourceDirectoryPE(uint depth, ResourceName name, Win32ResourcesPE resources, IBinaryReader reader) : base(name) { this.resources = resources; this.depth = depth; Initialize(reader); } /// /// Reads the directory header and initializes and /// . /// /// void Initialize(IBinaryReader reader) { if (depth > MAX_DIR_DEPTH || !reader.CanRead(16)) { InitializeDefault(); return; } characteristics = reader.ReadUInt32(); timeDateStamp = reader.ReadUInt32(); majorVersion = reader.ReadUInt16(); minorVersion = reader.ReadUInt16(); ushort numNamed = reader.ReadUInt16(); ushort numIds = reader.ReadUInt16(); int total = numNamed + numIds; if (!reader.CanRead(total * 8)) { InitializeDefault(); return; } dataInfos = new List(); dirInfos = new List(); long offset = reader.Position; for (int i = 0; i < total; i++, offset += 8) { reader.Position = offset; uint nameOrId = reader.ReadUInt32(); uint dataOrDirectory = reader.ReadUInt32(); ResourceName name; if ((nameOrId & 0x80000000) != 0) name = new ResourceName(ReadString(reader, nameOrId & 0x7FFFFFFF) ?? string.Empty); else name = new ResourceName((int)nameOrId); if ((dataOrDirectory & 0x80000000) == 0) dataInfos.Add(new EntryInfo(name, dataOrDirectory)); else dirInfos.Add(new EntryInfo(name, dataOrDirectory & 0x7FFFFFFF)); } directories = new LazyList(dirInfos.Count, null, (ctx, i) => ReadResourceDirectory((int)i)); data = new LazyList(dataInfos.Count, null, (ctx, i) => ReadResourceData((int)i)); } /// /// Reads a string /// /// Reader /// Offset of string /// The string or null if we could not read it static string ReadString(IBinaryReader reader, uint offset) { reader.Position = offset; if (!reader.CanRead(2)) return null; int size = reader.ReadUInt16(); int sizeInBytes = size * 2; if (!reader.CanRead(sizeInBytes)) return null; var stringData = reader.ReadBytes(sizeInBytes); try { return Encoding.Unicode.GetString(stringData); } catch { return null; } } ResourceDirectory ReadResourceDirectory(int i) { #if THREAD_SAFE resources.theLock.EnterWriteLock(); try { #endif var info = dirInfos[i]; var reader = resources.ResourceReader; var oldPos = reader.Position; reader.Position = info.offset; var dir = new ResourceDirectoryPE(depth + 1, info.name, resources, reader); reader.Position = oldPos; return dir; #if THREAD_SAFE } finally { resources.theLock.ExitWriteLock(); } #endif } ResourceData ReadResourceData(int i) { #if THREAD_SAFE resources.theLock.EnterWriteLock(); try { #endif var info = dataInfos[i]; var reader = resources.ResourceReader; var oldPos = reader.Position; reader.Position = info.offset; ResourceData data; if (reader.CanRead(16)) { RVA rva = (RVA)reader.ReadUInt32(); uint size = reader.ReadUInt32(); uint codePage = reader.ReadUInt32(); uint reserved = reader.ReadUInt32(); var dataReader = resources.CreateDataReader_NoLock(rva, size); data = new ResourceData(info.name, dataReader, codePage, reserved); } else data = new ResourceData(info.name, MemoryImageStream.CreateEmpty()); reader.Position = oldPos; return data; #if THREAD_SAFE } finally { resources.theLock.ExitWriteLock(); } #endif } void InitializeDefault() { directories = new LazyList(); data = new LazyList(); } } } dnlib-2.1_VS2010/src/W32Resources/ResourceDirectoryEntry.cs000066400000000000000000000012301325033663500234430ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info namespace dnlib.W32Resources { /// /// Base class of and /// public abstract class ResourceDirectoryEntry { ResourceName name; /// /// Gets/sets the name /// public ResourceName Name { get { return name; } set { name = value; } } /// /// Constructor /// /// Name protected ResourceDirectoryEntry(ResourceName name) { this.name = name; } /// public override string ToString() { return name.ToString(); } } } dnlib-2.1_VS2010/src/W32Resources/ResourceName.cs000066400000000000000000000063521325033663500213470ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; namespace dnlib.W32Resources { /// /// A Win32 resource name. It can be either an integer or a string. /// public struct ResourceName : IComparable, IEquatable { readonly int id; readonly string name; /// /// true if is valid /// public bool HasId { get { return name == null; } } /// /// true if is valid /// public bool HasName { get { return name != null; } } /// /// The ID. It's only valid if is true /// public int Id { get { return id; } } /// /// The name. It's only valid if is true /// public string Name { get { return name; } } /// /// Constructor /// /// ID public ResourceName(int id) { this.id = id; this.name = null; } /// /// Constructor /// /// Name public ResourceName(string name) { this.id = 0; this.name = name; } /// Converts input to a public static implicit operator ResourceName(int id) { return new ResourceName(id); } /// Converts input to a public static implicit operator ResourceName(string name) { return new ResourceName(name); } /// Overloaded operator public static bool operator <(ResourceName left, ResourceName right) { return left.CompareTo(right) < 0; } /// Overloaded operator public static bool operator <=(ResourceName left, ResourceName right) { return left.CompareTo(right) <= 0; } /// Overloaded operator public static bool operator >(ResourceName left, ResourceName right) { return left.CompareTo(right) > 0; } /// Overloaded operator public static bool operator >=(ResourceName left, ResourceName right) { return left.CompareTo(right) >= 0; } /// Overloaded operator public static bool operator ==(ResourceName left, ResourceName right) { return left.Equals(right); } /// Overloaded operator public static bool operator !=(ResourceName left, ResourceName right) { return !left.Equals(right); } /// public int CompareTo(ResourceName other) { if (HasId != other.HasId) { // Sort names before ids return HasName ? -1 : 1; } if (HasId) return id.CompareTo(other.id); else return name.ToUpperInvariant().CompareTo(other.name.ToUpperInvariant()); } /// public bool Equals(ResourceName other) { return CompareTo(other) == 0; } /// public override bool Equals(object obj) { if (!(obj is ResourceName)) return false; return Equals((ResourceName)obj); } /// public override int GetHashCode() { if (HasId) return id; return name.GetHashCode(); } /// public override string ToString() { return HasId ? id.ToString() : name; } } } dnlib-2.1_VS2010/src/W32Resources/Win32Resources.cs000066400000000000000000000163341325033663500215550ustar00rootroot00000000000000// dnlib: See LICENSE.txt for more info using System; using System.Threading; using dnlib.Utils; using dnlib.IO; using dnlib.PE; using dnlib.Threading; namespace dnlib.W32Resources { /// /// Win32 resources base class /// public abstract class Win32Resources : IDisposable { /// /// Gets/sets the root directory /// public abstract ResourceDirectory Root { get; set; } /// /// Finds a /// /// Type /// The or null if none found public ResourceDirectory Find(ResourceName type) { var dir = Root; if (dir == null) return null; return dir.FindDirectory(type); } /// /// Finds a /// /// Type /// Name /// The or null if none found public ResourceDirectory Find(ResourceName type, ResourceName name) { var dir = Find(type); if (dir == null) return null; return dir.FindDirectory(name); } /// /// Finds a /// /// Type /// Name /// Language ID /// The or null if none found public ResourceData Find(ResourceName type, ResourceName name, ResourceName langId) { var dir = Find(type, name); if (dir == null) return null; return dir.FindData(langId); } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose method /// /// true if called by protected virtual void Dispose(bool disposing) { if (!disposing) return; Root = null; // Property handler will call Dispose() } } /// /// Win32 resources class created by the user /// public class Win32ResourcesUser : Win32Resources { ResourceDirectory root = new ResourceDirectoryUser(new ResourceName("root")); /// public override ResourceDirectory Root { get { return root; } set { var oldValue = Interlocked.Exchange(ref root, value); if (oldValue != value && oldValue != null) oldValue.Dispose(); } } } /// /// Win32 resources class created from a PE file /// public sealed class Win32ResourcesPE : Win32Resources { /// /// Converts data RVAs to file offsets in /// readonly IRvaFileOffsetConverter rvaConverter; /// /// This reader only reads the raw data. The data RVA is found in the data header and /// it's first converted to a file offset using . This file /// offset is where we'll read from using this reader. /// IImageStream dataReader; /// /// This reader only reads the directory entries and data headers. The data is read /// by /// IBinaryReader rsrcReader; UserValue root; #if THREAD_SAFE internal readonly Lock theLock = Lock.Create(); #endif /// public override ResourceDirectory Root { get { return root.Value; } set { IDisposable origValue = null; if (root.IsValueInitialized) { origValue = root.Value; if (origValue == value) return; } root.Value = value; if (origValue != null) origValue.Dispose(); } } /// /// Gets the resource reader /// internal IBinaryReader ResourceReader { get { return rsrcReader; } } /// /// Constructor /// /// / converter /// Data reader (it's used after converting an /// to a ). This instance owns the reader. /// Reader for the whole Win32 resources section (usually /// the .rsrc section). It's used to read 's and /// 's but not the actual data blob. This instance owns the /// reader. public Win32ResourcesPE(IRvaFileOffsetConverter rvaConverter, IImageStream dataReader, IBinaryReader rsrcReader) { if (dataReader == rsrcReader) rsrcReader = dataReader.Clone(); // Must not be the same readers this.rvaConverter = rvaConverter; this.dataReader = dataReader; this.rsrcReader = rsrcReader; Initialize(); } /// /// Constructor /// /// The PE image public Win32ResourcesPE(IPEImage peImage) : this(peImage, null) { } /// /// Constructor /// /// The PE image /// Reader for the whole Win32 resources section (usually /// the .rsrc section) or null if we should create one from the resource data /// directory in the optional header. This instance owns the reader. public Win32ResourcesPE(IPEImage peImage, IBinaryReader rsrcReader) { this.rvaConverter = peImage; this.dataReader = peImage.CreateFullStream(); if (rsrcReader != null) this.rsrcReader = rsrcReader; else { var dataDir = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[2]; if (dataDir.VirtualAddress != 0 && dataDir.Size != 0) this.rsrcReader = peImage.CreateStream(dataDir.VirtualAddress, dataDir.Size); else this.rsrcReader = MemoryImageStream.CreateEmpty(); } Initialize(); } void Initialize() { root.ReadOriginalValue = () => { if (rsrcReader == null) return null; // It's disposed long oldPos = rsrcReader.Position; rsrcReader.Position = 0; var dir = new ResourceDirectoryPE(0, new ResourceName("root"), this, rsrcReader); rsrcReader.Position = oldPos; return dir; }; #if THREAD_SAFE root.Lock = theLock; #endif } /// /// Creates a new data reader /// /// RVA of data /// Size of data /// A new for this data public IBinaryReader CreateDataReader(RVA rva, uint size) { #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif return CreateDataReader_NoLock(rva, size); #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif } internal IBinaryReader CreateDataReader_NoLock(RVA rva, uint size) { var reader = dataReader.Create(rvaConverter.ToFileOffset(rva), size); if (reader.Length == size) return reader; reader.Dispose(); return MemoryImageStream.CreateEmpty(); } /// protected override void Dispose(bool disposing) { if (!disposing) return; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif if (dataReader != null) dataReader.Dispose(); if (rsrcReader != null) rsrcReader.Dispose(); dataReader = null; rsrcReader = null; #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif base.Dispose(disposing); } } } dnlib-2.1_VS2010/src/dnlib.csproj000066400000000000000000000573361325033663500165040ustar00rootroot00000000000000 Debug AnyCPU 8.0.30703 2.0 {FDFC1237-143F-4919-8318-4926901F4639} Library Properties dnlib dnlib v2.0 512 true ..\dnlib.snk 4 true /usr/lib/mono/2.0-api /usr/local/lib/mono/2.0-api /Library/Frameworks/Mono.framework/Versions/Current/lib/mono/2.0-api /usr/local/Cellar/mono/4.6.2.16/lib/mono/2.0-api true full false ..\Debug\bin\ TRACE;DEBUG;$(MoreDefineConstants) prompt 4 ..\Debug\bin\dnlib.xml true pdbonly true ..\Release\bin\ TRACE;$(MoreDefineConstants) prompt 4 ..\Release\bin\dnlib.xml true LICENSE.txt README.md dnlib-2.1_VS2010/src/dnlib.netstandard.csproj000066400000000000000000000020661325033663500210000ustar00rootroot00000000000000 netstandard2.0 dnlib dnlib true true ..\dnlib.snk true ..\$(Configuration)\bin $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml false