diff --git a/Mono.Cecil/Mono.Cecil.Cil/CodeReader.cs b/Mono.Cecil/Mono.Cecil.Cil/CodeReader.cs index 4141617f1..12ca5a23b 100644 --- a/Mono.Cecil/Mono.Cecil.Cil/CodeReader.cs +++ b/Mono.Cecil/Mono.Cecil.Cil/CodeReader.cs @@ -102,7 +102,7 @@ namespace Mono.Cecil.Cil { throw new InvalidOperationException (); } - var symbol_reader = reader.module.SymbolReader; + var symbol_reader = reader.module.symbol_reader; if (symbol_reader != null) { var instructions = body.Instructions; @@ -409,7 +409,7 @@ namespace Mono.Cecil.Cil { throw new NotSupportedException (); } - var symbol_reader = reader.module.SymbolReader; + var symbol_reader = reader.module.symbol_reader; if (symbol_reader != null && writer.metadata.write_symbols) { symbols.method_token = GetOriginalToken (writer.metadata, method); symbols.local_var_token = local_var_token; diff --git a/Mono.Cecil/Mono.Cecil.Cil/CodeWriter.cs b/Mono.Cecil/Mono.Cecil.Cil/CodeWriter.cs index 02876aad5..ac093cae4 100644 --- a/Mono.Cecil/Mono.Cecil.Cil/CodeWriter.cs +++ b/Mono.Cecil/Mono.Cecil.Cil/CodeWriter.cs @@ -424,10 +424,18 @@ namespace Mono.Cecil.Cil { switch (instruction.opcode.FlowControl) { case FlowControl.Call: { var method = (IMethodSignature) instruction.operand; - stack_size -= (method.HasParameters ? method.Parameters.Count : 0) - + (method.HasThis && instruction.opcode.Code != Code.Newobj ? 1 : 0); - stack_size += (method.ReturnType.etype == ElementType.Void ? 0 : 1) - + (method.HasThis && instruction.opcode.Code == Code.Newobj ? 1 : 0); + // pop 'this' argument + if (method.HasImplicitThis() && instruction.opcode.Code != Code.Newobj) + stack_size--; + // pop normal arguments + if (method.HasParameters) + stack_size -= method.Parameters.Count; + // pop function pointer + if (instruction.opcode.Code == Code.Calli) + stack_size--; + // push return value + if (method.ReturnType.etype != ElementType.Void || instruction.opcode.Code == Code.Newobj) + stack_size++; break; } default: diff --git a/Mono.Cecil/Mono.Cecil.PE/Image.cs b/Mono.Cecil/Mono.Cecil.PE/Image.cs index 9a04494f0..a11cf1c40 100644 --- a/Mono.Cecil/Mono.Cecil.PE/Image.cs +++ b/Mono.Cecil/Mono.Cecil.PE/Image.cs @@ -41,6 +41,7 @@ namespace Mono.Cecil.PE { public ModuleKind Kind; public TargetRuntime Runtime; public TargetArchitecture Architecture; + public ModuleCharacteristics Characteristics; public string FileName; public Section [] Sections; @@ -52,6 +53,7 @@ namespace Mono.Cecil.PE { public DataDirectory Debug; public DataDirectory Resources; + public DataDirectory StrongName; public StringHeap StringHeap; public BlobHeap BlobHeap; diff --git a/Mono.Cecil/Mono.Cecil.PE/ImageReader.cs b/Mono.Cecil/Mono.Cecil.PE/ImageReader.cs index 0714e7559..c96c1db31 100644 --- a/Mono.Cecil/Mono.Cecil.PE/ImageReader.cs +++ b/Mono.Cecil/Mono.Cecil.PE/ImageReader.cs @@ -99,13 +99,14 @@ namespace Mono.Cecil.PE { // Characteristics 2 ushort characteristics = ReadUInt16 (); - ushort subsystem; - ReadOptionalHeaders (out subsystem); + ushort subsystem, dll_characteristics; + ReadOptionalHeaders (out subsystem, out dll_characteristics); ReadSections (sections); ReadCLIHeader (); ReadMetadata (); image.Kind = GetModuleKind (characteristics, subsystem); + image.Characteristics = (ModuleCharacteristics) dll_characteristics; } TargetArchitecture ReadArchitecture () @@ -122,7 +123,7 @@ namespace Mono.Cecil.PE { return TargetArchitecture.ARMv7; } - throw new NotSupportedException (machine.ToString()); + throw new NotSupportedException (); } static ModuleKind GetModuleKind (ushort characteristics, ushort subsystem) @@ -136,7 +137,7 @@ namespace Mono.Cecil.PE { return ModuleKind.Console; } - void ReadOptionalHeaders (out ushort subsystem) + void ReadOptionalHeaders (out ushort subsystem, out ushort dll_characteristics) { // - PEOptionalHeader // - StandardFieldsHeader @@ -176,6 +177,7 @@ namespace Mono.Cecil.PE { subsystem = ReadUInt16 (); // DLLFlags 2 + dll_characteristics = ReadUInt16 (); // StackReserveSize 4 || 8 // StackCommitSize 4 || 8 // HeapReserveSize 4 || 8 @@ -192,7 +194,7 @@ namespace Mono.Cecil.PE { // CertificateTable 8 // BaseRelocationTable 8 - Advance (pe64 ? 90 : 74); + Advance (pe64 ? 88 : 72); // Debug 8 image.Debug = ReadDataDirectory (); @@ -322,6 +324,7 @@ namespace Mono.Cecil.PE { // Resources 8 image.Resources = ReadDataDirectory (); // StrongNameSignature 8 + image.StrongName = ReadDataDirectory (); // CodeManagerTable 8 // VTableFixups 8 // ExportAddressTableJumps 8 diff --git a/Mono.Cecil/Mono.Cecil.PE/ImageWriter.cs b/Mono.Cecil/Mono.Cecil.PE/ImageWriter.cs index af6aa7a35..c62427c6a 100644 --- a/Mono.Cecil/Mono.Cecil.PE/ImageWriter.cs +++ b/Mono.Cecil/Mono.Cecil.PE/ImageWriter.cs @@ -75,7 +75,7 @@ namespace Mono.Cecil.PE { this.GetDebugHeader (); this.GetWin32Resources (); this.text_map = BuildTextMap (); - this.sections = 2; // text + reloc + this.sections = (ushort) (pe64 ? 1 : 2); // text + reloc this.time_stamp = (uint) DateTime.UtcNow.Subtract (new DateTime (1970, 1, 1)).TotalSeconds; } @@ -133,7 +133,8 @@ namespace Mono.Cecil.PE { previous = rsrc; } - reloc = CreateSection (".reloc", 12u, previous); + if (!pe64) + reloc = CreateSection (".reloc", 12u, previous); } Section CreateSection (string name, uint size, Section previous) @@ -217,20 +218,29 @@ namespace Mono.Cecil.PE { throw new NotSupportedException (); } + Section LastSection () + { + if (reloc != null) + return reloc; + + if (rsrc != null) + return rsrc; + + return text; + } + void WriteOptionalHeaders () { WriteUInt16 ((ushort) (!pe64 ? 0x10b : 0x20b)); // Magic WriteByte (8); // LMajor WriteByte (0); // LMinor WriteUInt32 (text.SizeOfRawData); // CodeSize - WriteUInt32 (reloc.SizeOfRawData + WriteUInt32 ((reloc != null ? reloc.SizeOfRawData : 0) + (rsrc != null ? rsrc.SizeOfRawData : 0)); // InitializedDataSize WriteUInt32 (0); // UninitializedDataSize - var entry_point_rva = text_map.GetRVA (TextSegment.StartupStub); - if (module.Architecture == TargetArchitecture.IA64) - entry_point_rva += 0x20; - WriteUInt32 (entry_point_rva); // EntryPointRVA + var startub_stub = text_map.GetRange (TextSegment.StartupStub); + WriteUInt32 (startub_stub.Length > 0 ? startub_stub.Start : 0); // EntryPointRVA WriteUInt32 (text_rva); // BaseOfCode if (!pe64) { @@ -251,12 +261,13 @@ namespace Mono.Cecil.PE { WriteUInt16 (0); // SubSysMinor WriteUInt32 (0); // Reserved - WriteUInt32 (reloc.VirtualAddress + Align (reloc.VirtualSize, section_alignment)); // ImageSize + var last_section = LastSection(); + WriteUInt32 (last_section.VirtualAddress + Align (last_section.VirtualSize, section_alignment)); // ImageSize WriteUInt32 (text.PointerToRawData); // HeaderSize WriteUInt32 (0); // Checksum WriteUInt16 (GetSubSystem ()); // SubSystem - WriteUInt16 (0x8540); // DLLFlags + WriteUInt16 ((ushort) module.Characteristics); // DLLFlags const ulong stack_reserve = 0x100000; const ulong stack_commit = 0x1000; @@ -288,8 +299,8 @@ namespace Mono.Cecil.PE { WriteZeroDataDirectory (); // ExceptionTable WriteZeroDataDirectory (); // CertificateTable - WriteUInt32 (reloc.VirtualAddress); // BaseRelocationTable - WriteUInt32 (reloc.VirtualSize); + WriteUInt32 (reloc != null ? reloc.VirtualAddress : 0); // BaseRelocationTable + WriteUInt32 (reloc != null ? reloc.VirtualSize : 0); if (text_map.GetLength (TextSegment.DebugDirectory) > 0) { WriteUInt32 (text_map.GetRVA (TextSegment.DebugDirectory)); @@ -335,7 +346,8 @@ namespace Mono.Cecil.PE { if (rsrc != null) WriteSection (rsrc, 0x40000040); - WriteSection (reloc, 0x42000040); + if (reloc != null) + WriteSection (reloc, 0x42000040); } void WriteSection (Section section, uint characteristics) @@ -386,8 +398,10 @@ namespace Mono.Cecil.PE { // ImportAddressTable - WriteRVA (text_map.GetRVA (TextSegment.ImportHintNameTable)); - WriteRVA (0); + if (!pe64) { + WriteRVA (text_map.GetRVA (TextSegment.ImportHintNameTable)); + WriteRVA (0); + } // CLIHeader @@ -439,6 +453,9 @@ namespace Mono.Cecil.PE { WriteDebugDirectory (); } + if (pe64) + return; + // ImportDirectory MoveToRVA (TextSegment.ImportDirectory); WriteImportDirectory (); @@ -605,19 +622,8 @@ namespace Mono.Cecil.PE { WriteUInt16 (0x25ff); WriteUInt32 ((uint) image_base + text_map.GetRVA (TextSegment.ImportAddressTable)); return; - case TargetArchitecture.AMD64: - WriteUInt16 (0xa148); - WriteUInt32 ((uint) image_base + text_map.GetRVA (TextSegment.ImportAddressTable)); - WriteUInt16 (0xe0ff); - return; - case TargetArchitecture.IA64: - WriteBytes (new byte [] { - 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 - }); - WriteUInt32 ((uint) image_base + text_map.GetRVA (TextSegment.StartupStub)); - WriteUInt32 ((uint) image_base + text_rva); - return; + default: + throw new NotSupportedException (); } } @@ -642,13 +648,8 @@ namespace Mono.Cecil.PE { case TargetArchitecture.I386: WriteUInt32 (0x3000 + reloc_rva - page_rva); break; - case TargetArchitecture.AMD64: - WriteUInt32 (0xa000 + reloc_rva - page_rva); - break; - case TargetArchitecture.IA64: - WriteUInt16 ((ushort) (0xa000 + reloc_rva - page_rva)); - WriteUInt16 ((ushort) (0xa000 + reloc_rva - page_rva + 8)); - break; + default: + throw new NotSupportedException(); } WriteBytes (new byte [file_alignment - reloc.VirtualSize]); @@ -663,7 +664,8 @@ namespace Mono.Cecil.PE { WriteText (); if (rsrc != null) WriteRsrc (); - WriteReloc (); + if (reloc != null) + WriteReloc (); } TextMap BuildTextMap () @@ -694,8 +696,16 @@ namespace Mono.Cecil.PE { map.AddMap (TextSegment.DebugDirectory, debug_dir_len, 4); + if (pe64) { + var start = map.GetNextRVA (TextSegment.DebugDirectory); + map.AddMap (TextSegment.ImportDirectory, new Range (start, 0)); + map.AddMap (TextSegment.ImportHintNameTable, new Range (start, 0)); + map.AddMap (TextSegment.StartupStub, new Range (start, 0)); + return map; + } + RVA import_dir_rva = map.GetNextRVA (TextSegment.DebugDirectory); - RVA import_hnt_rva = import_dir_rva + (!pe64 ? 48u : 52u); + RVA import_hnt_rva = import_dir_rva + 48u; import_hnt_rva = (import_hnt_rva + 15u) & ~15u; uint import_dir_len = (import_hnt_rva - import_dir_rva) + 27u; @@ -716,12 +726,8 @@ namespace Mono.Cecil.PE { switch (module.Architecture) { case TargetArchitecture.I386: return 6; - case TargetArchitecture.AMD64: - return 12; - case TargetArchitecture.IA64: - return 48; default: - throw new InvalidOperationException (); + throw new NotSupportedException (); } } @@ -744,24 +750,22 @@ namespace Mono.Cecil.PE { int GetStrongNameLength () { - if ((module.Attributes & ModuleAttributes.StrongNameSigned) == 0) - return 0; - if (module.Assembly == null) - throw new InvalidOperationException (); + return 0; var public_key = module.Assembly.Name.PublicKey; + if (public_key.IsNullOrEmpty ()) + return 0; - if (public_key != null) { - // in fx 2.0 the key may be from 384 to 16384 bits - // so we must calculate the signature size based on - // the size of the public key (minus the 32 byte header) - int size = public_key.Length; - if (size > 32) - return size - 32; - // note: size == 16 for the ECMA "key" which is replaced - // by the runtime with a 1024 bits key (128 bytes) - } + // in fx 2.0 the key may be from 384 to 16384 bits + // so we must calculate the signature size based on + // the size of the public key (minus the 32 byte header) + int size = public_key.Length; + if (size > 32) + return size - 32; + + // note: size == 16 for the ECMA "key" which is replaced + // by the runtime with a 1024 bits key (128 bytes) return 128; // default strongname signature size } diff --git a/Mono.Cecil/Mono.Cecil.nuspec b/Mono.Cecil/Mono.Cecil.nuspec index 021e794e6..ffab04f49 100644 --- a/Mono.Cecil/Mono.Cecil.nuspec +++ b/Mono.Cecil/Mono.Cecil.nuspec @@ -2,7 +2,7 @@ Mono.Cecil - 0.9.5.2 + 0.9.5.3 Mono.Cecil Jb Evain Jb Evain diff --git a/Mono.Cecil/Mono.Cecil/AssemblyNameReference.cs b/Mono.Cecil/Mono.Cecil/AssemblyNameReference.cs index 063bc5b62..a8ad42c3c 100644 --- a/Mono.Cecil/Mono.Cecil/AssemblyNameReference.cs +++ b/Mono.Cecil/Mono.Cecil/AssemblyNameReference.cs @@ -98,7 +98,7 @@ namespace Mono.Cecil { } public byte [] PublicKey { - get { return public_key; } + get { return public_key ?? Empty.Array; } set { public_key = value; HasPublicKey = !public_key.IsNullOrEmpty (); @@ -117,7 +117,7 @@ namespace Mono.Cecil { Array.Reverse (local_public_key_token, 0, 8); public_key_token = local_public_key_token; // publish only once finished (required for thread-safety) } - return public_key_token; + return public_key_token ?? Empty.Array; } set { public_key_token = value; @@ -176,9 +176,10 @@ namespace Mono.Cecil { builder.Append (sep); builder.Append ("PublicKeyToken="); - if (this.PublicKeyToken != null && public_key_token.Length > 0) { - for (int i = 0 ; i < public_key_token.Length ; i++) { - builder.Append (public_key_token [i].ToString ("x2")); + var pk_token = PublicKeyToken; + if (!pk_token.IsNullOrEmpty () && pk_token.Length > 0) { + for (int i = 0 ; i < pk_token.Length ; i++) { + builder.Append (pk_token [i].ToString ("x2")); } } else builder.Append ("null"); diff --git a/Mono.Cecil/Mono.Cecil/AssemblyReader.cs b/Mono.Cecil/Mono.Cecil/AssemblyReader.cs index de296e789..00eba7437 100644 --- a/Mono.Cecil/Mono.Cecil/AssemblyReader.cs +++ b/Mono.Cecil/Mono.Cecil/AssemblyReader.cs @@ -778,8 +778,12 @@ namespace Mono.Cecil { var nested_types = new MemberDefinitionCollection (type, mapping.Length); - for (int i = 0; i < mapping.Length; i++) - nested_types.Add (GetTypeDefinition (mapping [i])); + for (int i = 0; i < mapping.Length; i++) { + var nested_type = GetTypeDefinition (mapping [i]); + + if (nested_type != null) + nested_types.Add (nested_type); + } metadata.RemoveNestedTypeMapping (type); diff --git a/Mono.Cecil/Mono.Cecil/AssemblyWriter.cs b/Mono.Cecil/Mono.Cecil/AssemblyWriter.cs index a2d3ffa41..bffa439c6 100644 --- a/Mono.Cecil/Mono.Cecil/AssemblyWriter.cs +++ b/Mono.Cecil/Mono.Cecil/AssemblyWriter.cs @@ -97,20 +97,18 @@ namespace Mono.Cecil { var symbol_writer = GetSymbolWriter (module, fq_name, symbol_writer_provider); #if !SILVERLIGHT && !CF - if (parameters.StrongNameKeyPair != null && name != null) + if (parameters.StrongNameKeyPair != null && name != null) { name.PublicKey = parameters.StrongNameKeyPair.PublicKey; -#endif - - if (name != null && name.HasPublicKey) module.Attributes |= ModuleAttributes.StrongNameSigned; - + } +#endif var metadata = new MetadataBuilder (module, fq_name, symbol_writer_provider, symbol_writer); BuildMetadata (module, metadata); - if (module.SymbolReader != null) - module.SymbolReader.Dispose (); + if (module.symbol_reader != null) + module.symbol_reader.Dispose (); var writer = ImageWriter.CreateWriter (module, metadata, stream); @@ -786,7 +784,7 @@ namespace Mono.Cecil { TextMap CreateTextMap () { var map = new TextMap (); - map.AddMap (TextSegment.ImportAddressTable, module.Architecture == TargetArchitecture.I386 ? 8 : 16); + map.AddMap (TextSegment.ImportAddressTable, module.Architecture == TargetArchitecture.I386 ? 8 : 0); map.AddMap (TextSegment.CLIHeader, 0x48, 8); return map; } diff --git a/Mono.Cecil/Mono.Cecil/DefaultAssemblyResolver.cs b/Mono.Cecil/Mono.Cecil/DefaultAssemblyResolver.cs index a9faa2142..e0baedf77 100644 --- a/Mono.Cecil/Mono.Cecil/DefaultAssemblyResolver.cs +++ b/Mono.Cecil/Mono.Cecil/DefaultAssemblyResolver.cs @@ -31,11 +31,6 @@ using System.Collections.Generic; namespace Mono.Cecil { - public static class GlobalAssemblyResolver { - - public static readonly IAssemblyResolver Instance = new DefaultAssemblyResolver (); - } - public class DefaultAssemblyResolver : BaseAssemblyResolver { readonly IDictionary cache; diff --git a/Mono.Cecil/Mono.Cecil/IMethodSignature.cs b/Mono.Cecil/Mono.Cecil/IMethodSignature.cs index 491deec5d..e3d288ba9 100644 --- a/Mono.Cecil/Mono.Cecil/IMethodSignature.cs +++ b/Mono.Cecil/Mono.Cecil/IMethodSignature.cs @@ -46,6 +46,11 @@ namespace Mono.Cecil { static partial class Mixin { + public static bool HasImplicitThis (this IMethodSignature self) + { + return self.HasThis && !self.ExplicitThis; + } + public static void MethodSignatureFullName (this IMethodSignature self, StringBuilder builder) { builder.Append ("("); diff --git a/Mono.Cecil/Mono.Cecil/Import.cs b/Mono.Cecil/Mono.Cecil/Import.cs index 4f3ff25c4..38d012041 100644 --- a/Mono.Cecil/Mono.Cecil/Import.cs +++ b/Mono.Cecil/Mono.Cecil/Import.cs @@ -92,7 +92,7 @@ namespace Mono.Cecil { if (IsNestedType (type)) reference.DeclaringType = ImportType (type.DeclaringType, context, import_kind); else - reference.Namespace = type.Namespace; + reference.Namespace = type.Namespace ?? string.Empty; if (type.IsGenericType) ImportGenericParameters (reference, type.GetGenericArguments ()); diff --git a/Mono.Cecil/Mono.Cecil/MetadataSystem.cs b/Mono.Cecil/Mono.Cecil/MetadataSystem.cs index d17a78386..72b04f285 100644 --- a/Mono.Cecil/Mono.Cecil/MetadataSystem.cs +++ b/Mono.Cecil/Mono.Cecil/MetadataSystem.cs @@ -102,8 +102,11 @@ namespace Mono.Cecil { public static void TryProcessPrimitiveTypeReference (TypeReference type) { + if (type.Namespace != "System") + return; + var scope = type.scope; - if (scope == null || scope.MetadataScopeType != MetadataScopeType.AssemblyNameReference || scope.Name != "mscorlib") + if (scope == null || scope.MetadataScopeType != MetadataScopeType.AssemblyNameReference) return; Row primitive_data; @@ -118,7 +121,7 @@ namespace Mono.Cecil { { etype = ElementType.None; - if (!type.HasImage || !type.Module.IsCorlib ()) + if (type.Namespace != "System") return false; Row primitive_data; @@ -132,11 +135,6 @@ namespace Mono.Cecil { static bool TryGetPrimitiveData (TypeReference type, out Row primitive_data) { - primitive_data = new Row (); - - if (type.Namespace != "System") - return false; - if (primitive_value_types == null) InitializePrimitives (); diff --git a/Mono.Cecil/Mono.Cecil/ModuleDefinition.cs b/Mono.Cecil/Mono.Cecil/ModuleDefinition.cs index 1b191815c..fc5b7a838 100644 --- a/Mono.Cecil/Mono.Cecil/ModuleDefinition.cs +++ b/Mono.Cecil/Mono.Cecil/ModuleDefinition.cs @@ -195,8 +195,8 @@ namespace Mono.Cecil { internal MetadataSystem MetadataSystem; internal ReadingMode ReadingMode; internal ISymbolReaderProvider SymbolReaderProvider; - internal ISymbolReader SymbolReader; + internal ISymbolReader symbol_reader; internal IAssemblyResolver assembly_resolver; internal IMetadataResolver metadata_resolver; internal TypeSystem type_system; @@ -208,6 +208,7 @@ namespace Mono.Cecil { TargetRuntime runtime; TargetArchitecture architecture; ModuleAttributes attributes; + ModuleCharacteristics characteristics; Guid mvid; internal AssemblyDefinition assembly; @@ -247,6 +248,11 @@ namespace Mono.Cecil { set { attributes = value; } } + public ModuleCharacteristics Characteristics { + get { return characteristics; } + set { characteristics = value; } + } + public string FullyQualifiedName { get { return fq_name; } } @@ -261,7 +267,11 @@ namespace Mono.Cecil { } public bool HasSymbols { - get { return SymbolReader != null; } + get { return symbol_reader != null; } + } + + public ISymbolReader SymbolReader { + get { return symbol_reader; } } public override MetadataScopeType MetadataScopeType { @@ -283,13 +293,13 @@ namespace Mono.Cecil { #endif public IAssemblyResolver AssemblyResolver { - get { return assembly_resolver; } + get { return assembly_resolver ?? (assembly_resolver = new DefaultAssemblyResolver ()); } } public IMetadataResolver MetadataResolver { get { if (metadata_resolver == null) - Interlocked.CompareExchange (ref metadata_resolver, new MetadataResolver (assembly_resolver), null); + Interlocked.CompareExchange (ref metadata_resolver, new MetadataResolver (this.AssemblyResolver), null); return metadata_resolver; } @@ -441,7 +451,6 @@ namespace Mono.Cecil { { this.MetadataSystem = new MetadataSystem (); this.token = new MetadataToken (TokenType.Module, 1); - this.assembly_resolver = GlobalAssemblyResolver.Instance; } internal ModuleDefinition (Image image) @@ -452,6 +461,7 @@ namespace Mono.Cecil { this.runtime = image.Runtime; this.architecture = image.Architecture; this.attributes = image.Attributes; + this.characteristics = image.Characteristics; this.fq_name = image.FileName; this.reader = new MetadataReader (this); @@ -859,15 +869,27 @@ namespace Mono.Cecil { } } + public bool HasDebugHeader { + get { return Image != null && !Image.Debug.IsZero; } + } + + public ImageDebugDirectory GetDebugHeader (out byte [] header) + { + if (!HasDebugHeader) + throw new InvalidOperationException (); + + return Image.GetDebugHeader (out header); + } + void ProcessDebugHeader () { - if (Image == null || Image.Debug.IsZero) + if (!HasDebugHeader) return; byte [] header; - var directory = Image.GetDebugHeader (out header); + var directory = GetDebugHeader (out header); - if (!SymbolReader.ProcessDebugHeader (directory, header)) + if (!symbol_reader.ProcessDebugHeader (directory, header)) throw new InvalidOperationException (); } @@ -890,6 +912,7 @@ namespace Mono.Cecil { architecture = parameters.Architecture, mvid = Guid.NewGuid (), Attributes = ModuleAttributes.ILOnly, + Characteristics = (ModuleCharacteristics) 0x8540, }; if (parameters.AssemblyResolver != null) @@ -937,7 +960,7 @@ namespace Mono.Cecil { if (reader == null) throw new ArgumentNullException ("reader"); - SymbolReader = reader; + symbol_reader = reader; ProcessDebugHeader (); } diff --git a/Mono.Cecil/Mono.Cecil/ModuleKind.cs b/Mono.Cecil/Mono.Cecil/ModuleKind.cs index d42c7bea2..c29da887d 100644 --- a/Mono.Cecil/Mono.Cecil/ModuleKind.cs +++ b/Mono.Cecil/Mono.Cecil/ModuleKind.cs @@ -41,7 +41,7 @@ namespace Mono.Cecil { I386, AMD64, IA64, - ARMv7 + ARMv7, } [Flags] @@ -49,6 +49,16 @@ namespace Mono.Cecil { ILOnly = 1, Required32Bit = 2, StrongNameSigned = 8, - Preferred32Bit = 0x00020000 + Preferred32Bit = 0x00020000, + } + + [Flags] + public enum ModuleCharacteristics { + HighEntropyVA = 0x0020, + DynamicBase = 0x0040, + NoSEH = 0x0400, + NXCompat = 0x0100, + AppContainer = 0x1000, + TerminalServerAware = 0x8000, } } diff --git a/Mono.Cecil/Mono.Cecil/ParameterDefinition.cs b/Mono.Cecil/Mono.Cecil/ParameterDefinition.cs index 1cac8e139..928da8940 100644 --- a/Mono.Cecil/Mono.Cecil/ParameterDefinition.cs +++ b/Mono.Cecil/Mono.Cecil/ParameterDefinition.cs @@ -54,7 +54,7 @@ namespace Mono.Cecil { if (method == null) return -1; - return method.HasThis ? index + 1 : index; + return method.HasImplicitThis () ? index + 1 : index; } } diff --git a/Mono.Cecil/Mono.Cecil/TypeParser.cs b/Mono.Cecil/Mono.Cecil/TypeParser.cs index 06dc935a5..3e633ea8d 100644 --- a/Mono.Cecil/Mono.Cecil/TypeParser.cs +++ b/Mono.Cecil/Mono.Cecil/TypeParser.cs @@ -272,7 +272,7 @@ namespace Mono.Cecil { public static TypeReference ParseType (ModuleDefinition module, string fullname) { - if (fullname == null) + if (string.IsNullOrEmpty (fullname)) return null; var parser = new TypeParser (fullname); diff --git a/Mono.Cecil/Mono.Cecil/TypeSystem.cs b/Mono.Cecil/Mono.Cecil/TypeSystem.cs index 0dd7701c6..a96fbb59b 100644 --- a/Mono.Cecil/Mono.Cecil/TypeSystem.cs +++ b/Mono.Cecil/Mono.Cecil/TypeSystem.cs @@ -34,14 +34,23 @@ namespace Mono.Cecil { public abstract class TypeSystem { - sealed class CorlibTypeSystem : TypeSystem { + sealed class CoreTypeSystem : TypeSystem { - public CorlibTypeSystem (ModuleDefinition module) + public CoreTypeSystem (ModuleDefinition module) : base (module) { } internal override TypeReference LookupType (string @namespace, string name) + { + var type = LookupTypeDefinition (@namespace, name) ?? LookupTypeForwarded (@namespace, name); + if (type != null) + return type; + + throw new NotSupportedException (); + } + + TypeReference LookupTypeDefinition (string @namespace, string name) { var metadata = module.MetadataSystem; if (metadata.Types == null) @@ -64,6 +73,22 @@ namespace Mono.Cecil { }); } + TypeReference LookupTypeForwarded (string @namespace, string name) + { + if (!module.HasExportedTypes) + return null; + + var exported_types = module.ExportedTypes; + for (int i = 0; i < exported_types.Count; i++) { + var exported_type = exported_types [i]; + + if (exported_type.Name == name && exported_type.Namespace == @namespace) + return exported_type.CreateReference (); + } + + return null; + } + static void Initialize (object obj) { } @@ -159,7 +184,7 @@ namespace Mono.Cecil { internal static TypeSystem CreateTypeSystem (ModuleDefinition module) { if (module.IsCorlib ()) - return new CorlibTypeSystem (module); + return new CoreTypeSystem (module); return new CommonTypeSystem (module); } diff --git a/Mono.Cecil/Test/Mono.Cecil.Tests.csproj b/Mono.Cecil/Test/Mono.Cecil.Tests.csproj index 31f297842..2ff2951f8 100644 --- a/Mono.Cecil/Test/Mono.Cecil.Tests.csproj +++ b/Mono.Cecil/Test/Mono.Cecil.Tests.csproj @@ -116,6 +116,7 @@ + diff --git a/Mono.Cecil/Test/Mono.Cecil.Tests/ImageReadTests.cs b/Mono.Cecil/Test/Mono.Cecil.Tests/ImageReadTests.cs index e77bfe066..8f68e5fc8 100644 --- a/Mono.Cecil/Test/Mono.Cecil.Tests/ImageReadTests.cs +++ b/Mono.Cecil/Test/Mono.Cecil.Tests/ImageReadTests.cs @@ -115,5 +115,30 @@ namespace Mono.Cecil.Tests { Assert.AreEqual (TargetArchitecture.I386, module.Image.Architecture); Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); } + + [TestModule ("delay-signed.dll")] + public void DelaySignedAssembly (ModuleDefinition module) + { + Assert.IsNotNull (module.Assembly.Name.PublicKey); + Assert.AreNotEqual (0, module.Assembly.Name.PublicKey.Length); + Assert.AreNotEqual (ModuleAttributes.StrongNameSigned, module.Attributes & ModuleAttributes.StrongNameSigned); + Assert.AreNotEqual (0, module.Image.StrongName.VirtualAddress); + Assert.AreNotEqual (0, module.Image.StrongName.Size); + } + + [TestModule ("wp7.dll", Verify = false)] + public void WindowsPhoneNonSignedAssembly (ModuleDefinition module) + { + Assert.AreEqual (0, module.Assembly.Name.PublicKey.Length); + Assert.AreNotEqual (ModuleAttributes.StrongNameSigned, module.Attributes & ModuleAttributes.StrongNameSigned); + Assert.AreEqual (0, module.Image.StrongName.VirtualAddress); + Assert.AreEqual (0, module.Image.StrongName.Size); + } + + [TestModule ("metro.exe", Verify = false)] + public void MetroAssembly (ModuleDefinition module) + { + Assert.AreEqual (ModuleCharacteristics.AppContainer, module.Characteristics & ModuleCharacteristics.AppContainer); + } } } diff --git a/Mono.Cecil/Test/Mono.Cecil.Tests/TypeTests.cs b/Mono.Cecil/Test/Mono.Cecil.Tests/TypeTests.cs index 878885b4a..3ceb0aa4d 100644 --- a/Mono.Cecil/Test/Mono.Cecil.Tests/TypeTests.cs +++ b/Mono.Cecil/Test/Mono.Cecil.Tests/TypeTests.cs @@ -209,5 +209,20 @@ namespace Mono.Cecil.Tests { Assert.IsTrue (int32_def.IsPrimitive); Assert.AreEqual (MetadataType.Int32, int32_def.MetadataType); } + + [TestIL ("explicitthis.il", Verify = false)] + public void ExplicitThis (ModuleDefinition module) + { + var type = module.GetType ("MakeDecision"); + var method = type.GetMethod ("Decide"); + var fptr = method.ReturnType as FunctionPointerType; + + Assert.IsNotNull (fptr); + Assert.IsTrue (fptr.HasThis); + Assert.IsTrue (fptr.ExplicitThis); + + Assert.AreEqual (0, fptr.Parameters [0].Sequence); + Assert.AreEqual (1, fptr.Parameters [1].Sequence); + } } } diff --git a/Mono.Cecil/Test/Resources/assemblies/delay-signed.dll b/Mono.Cecil/Test/Resources/assemblies/delay-signed.dll new file mode 100644 index 000000000..3571ccfd4 Binary files /dev/null and b/Mono.Cecil/Test/Resources/assemblies/delay-signed.dll differ diff --git a/Mono.Cecil/Test/Resources/assemblies/metro.exe b/Mono.Cecil/Test/Resources/assemblies/metro.exe new file mode 100644 index 000000000..68784b316 Binary files /dev/null and b/Mono.Cecil/Test/Resources/assemblies/metro.exe differ diff --git a/Mono.Cecil/Test/Resources/assemblies/wp7.dll b/Mono.Cecil/Test/Resources/assemblies/wp7.dll new file mode 100644 index 000000000..c3cbf7b6f Binary files /dev/null and b/Mono.Cecil/Test/Resources/assemblies/wp7.dll differ diff --git a/Mono.Cecil/Test/Resources/il/explicitthis.il b/Mono.Cecil/Test/Resources/il/explicitthis.il new file mode 100644 index 000000000..59b332769 --- /dev/null +++ b/Mono.Cecil/Test/Resources/il/explicitthis.il @@ -0,0 +1,113 @@ +.assembly extern mscorlib +{ + .ver 0:0:0:0 +} + +.assembly fptr +{ + .ver 0:0:0:0 +} +.module fptr.exe + +.method public static void Main() cil managed +{ + .entrypoint + .locals init (class MakeDecision d, method instance explicit int32 *(class MakeDecision, int32) m, int32 i) + + ldc.i4.1 + ldc.i4 42 + newobj instance void MakeDecision::.ctor(bool, int32) + stloc d + + ldc.i4.0 + stloc i + br test + +loop: + ldloc d + call instance method instance explicit int32 *(class MakeDecision, int32) MakeDecision::Decide() + stloc m + + ldloc d + ldc.i4.1 + ldloc m + calli instance int32(int32) + call void [mscorlib]System.Console::WriteLine(int32) + + ldloc i + ldc.i4.1 + add + stloc i + +test: + ldloc i + ldc.i4 10 + blt loop + + ret +} + +.class public auto ansi sealed MakeDecision + extends [mscorlib]System.Object +{ + .field private bool Oscillate + .field private int32 Value + + .method public instance method instance explicit int32 *(class MakeDecision, int32) Decide() cil managed + { + .locals init (bool t) + + ldarg.0 + ldfld bool MakeDecision::Oscillate + stloc t + + ldarg.0 + ldloc t + ldc.i4.0 + ceq + stfld bool MakeDecision::Oscillate + + ldloc t + brfalse subs + + ldftn instance int32 MakeDecision::Add(int32) + ret + + subs: + ldftn instance int32 MakeDecision::Sub(int32) + ret + } + + .method public int32 Add(int32 i) cil managed + { + ldarg.0 + ldfld int32 MakeDecision::Value + ldarg i + add + ret + } + + .method public int32 Sub(int32 i) cil managed + { + ldarg.0 + ldfld int32 MakeDecision::Value + ldarg i + sub + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor(bool s, int32 val) cil managed + { + ldarg.0 + ldarg s + stfld bool MakeDecision::Oscillate + + ldarg.0 + ldarg val + stfld int32 MakeDecision::Value + + ldarg.0 + call instance void [mscorlib]System.Object::.ctor() + ret + } +} diff --git a/Mono.Cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs b/Mono.Cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs index 937b0a516..6ad39d237 100644 --- a/Mono.Cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs +++ b/Mono.Cecil/symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs @@ -446,6 +446,11 @@ namespace Mono.CompilerServices.SymbolWriter protected MonoSymbolFile (string filename, Mono.Cecil.ModuleDefinition module) : this (filename) { + // Check that the MDB file matches the module, if we have been + // passed a module. + if (module == null) + return; + CheckGuidMatch (module.Mvid, filename, module.FullyQualifiedName); } @@ -485,7 +490,7 @@ namespace Mono.CompilerServices.SymbolWriter public static MonoSymbolFile ReadSymbolFile (string mdbFilename) { - return new MonoSymbolFile (mdbFilename, null); + return new MonoSymbolFile (mdbFilename); } public int CompileUnitCount {