diff options
author | Marek Safar <marek.safar@gmail.com> | 2017-02-14 00:41:38 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2017-02-14 00:41:38 +0300 |
commit | aae16928bc94a24bc901ea4780712e79606ddd11 (patch) | |
tree | e0cc654eb97a9bd299c60aeea90deeb6674a80d0 | |
parent | 96c5c284af2832be96644150868685fc73c85947 (diff) | |
parent | 2f13ff507824f64c90c78210a91d3a505cc9e6a5 (diff) |
Merge remote-tracking branch 'upstream/master'
31 files changed, 397 insertions, 149 deletions
diff --git a/Mono.Cecil.Cil/PortablePdb.cs b/Mono.Cecil.Cil/PortablePdb.cs index 4df8813..f7cb061 100644 --- a/Mono.Cecil.Cil/PortablePdb.cs +++ b/Mono.Cecil.Cil/PortablePdb.cs @@ -248,7 +248,13 @@ namespace Mono.Cecil.Cil { if (IsEmbedded) return; + WritePdbFile (); + } + + void WritePdbFile () + { WritePdbHeap (); + WriteTableHeap (); writer.BuildMetadataTextMap (); @@ -291,6 +297,10 @@ namespace Mono.Cecil.Cil { void WriteTableHeap () { + if (module_metadata.string_heap != pdb_metadata.string_heap) { + pdb_metadata.table_heap.string_offsets = pdb_metadata.string_heap.WriteStrings (); + } + pdb_metadata.table_heap.WriteTableHeap (); } } diff --git a/Mono.Cecil.Cil/Symbols.cs b/Mono.Cecil.Cil/Symbols.cs index 485152f..62ff6c9 100644 --- a/Mono.Cecil.Cil/Symbols.cs +++ b/Mono.Cecil.Cil/Symbols.cs @@ -630,16 +630,69 @@ namespace Mono.Cecil.Cil { } #if !PCL - static class SymbolProvider { + public class DefaultSymbolReaderProvider : ISymbolReaderProvider { + + readonly bool throw_if_no_symbol; + + public DefaultSymbolReaderProvider () + : this (throwIfNoSymbol: true) + { + } - static readonly string symbol_kind = Type.GetType ("Mono.Runtime") != null ? "Mdb" : "Pdb"; + public DefaultSymbolReaderProvider (bool throwIfNoSymbol) + { + throw_if_no_symbol = throwIfNoSymbol; + } - static SR.AssemblyName GetPlatformSymbolAssemblyName () + public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName) { + if (module.Image.HasDebugTables ()) + return null; + + var pdb_file_name = Mixin.GetPdbFileName (fileName); + + if (File.Exists (pdb_file_name)) + return Mixin.IsPortablePdb (Mixin.GetPdbFileName (fileName)) + ? new PortablePdbReaderProvider ().GetSymbolReader (module, fileName) + : SymbolProvider.GetReaderProvider (SymbolKind.NativePdb).GetSymbolReader (module, fileName); + + var mdb_file_name = Mixin.GetMdbFileName (fileName); + if (File.Exists (mdb_file_name)) + return SymbolProvider.GetReaderProvider (SymbolKind.Mdb).GetSymbolReader (module, fileName); + + if (throw_if_no_symbol) + throw new FileNotFoundException (string.Format ("No symbol found for file: {0}", fileName)); + + return null; + } + + public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream) + { + throw new NotSupportedException (); + } + } +#endif + +#if !PCL + enum SymbolKind { + NativePdb, + PortablePdb, + Mdb, + } + + static class SymbolProvider { + + static SR.AssemblyName GetSymbolAssemblyName (SymbolKind kind) + { + if (kind == SymbolKind.PortablePdb) + throw new ArgumentException (); + + var suffix = GetSymbolNamespace (kind); + var cecil_name = typeof (SymbolProvider).GetAssembly ().GetName (); var name = new SR.AssemblyName { - Name = "Mono.Cecil." + symbol_kind, + Name = cecil_name.Name + "." + suffix, Version = cecil_name.Version, }; @@ -648,13 +701,13 @@ namespace Mono.Cecil.Cil { return name; } - static Type GetPlatformType (string fullname) + static Type GetSymbolType (SymbolKind kind, string fullname) { var type = Type.GetType (fullname); if (type != null) return type; - var assembly_name = GetPlatformSymbolAssemblyName (); + var assembly_name = GetSymbolAssemblyName (kind); type = Type.GetType (fullname + ", " + assembly_name.FullName); if (type != null) @@ -671,39 +724,60 @@ namespace Mono.Cecil.Cil { return null; } - static ISymbolReaderProvider reader_provider; - - public static ISymbolReaderProvider GetPlatformReaderProvider () + public static ISymbolReaderProvider GetReaderProvider (SymbolKind kind) { - if (reader_provider != null) - return reader_provider; + if (kind == SymbolKind.PortablePdb) + return new PortablePdbReaderProvider (); - var type = GetPlatformType (GetProviderTypeName ("ReaderProvider")); + var type = GetSymbolType (kind, GetSymbolTypeName (kind, "ReaderProvider")); if (type == null) return null; - return reader_provider = (ISymbolReaderProvider) Activator.CreateInstance (type); + return (ISymbolReaderProvider) Activator.CreateInstance (type); } - static string GetProviderTypeName (string name) + static string GetSymbolTypeName (SymbolKind kind, string name) { - return "Mono.Cecil." + symbol_kind + "." + symbol_kind + name; + var ns = GetSymbolNamespace (kind); + return typeof (SymbolProvider).Assembly.GetName ().Name + "." + ns + "." + kind + name; } -#if !READ_ONLY + static string GetSymbolNamespace (SymbolKind kind) + { + if (kind == SymbolKind.PortablePdb) + return "Cil"; + if (kind == SymbolKind.NativePdb) + return "Pdb"; + if (kind == SymbolKind.Mdb) + return "Mdb"; + + throw new ArgumentException (); + } - static ISymbolWriterProvider writer_provider; +#if !READ_ONLY - public static ISymbolWriterProvider GetPlatformWriterProvider () + public static ISymbolWriterProvider GetWriterProvider (SymbolKind kind) { - if (writer_provider != null) - return writer_provider; + if (kind == SymbolKind.PortablePdb) + return new PortablePdbWriterProvider (); - var type = GetPlatformType (GetProviderTypeName ("WriterProvider")); + var type = GetSymbolType (kind, GetSymbolTypeName (kind, "WriterProvider")); if (type == null) return null; - return writer_provider = (ISymbolWriterProvider) Activator.CreateInstance (type); + return (ISymbolWriterProvider) Activator.CreateInstance (type); + } + + public static SymbolKind GetSymbolKind (Type type) + { + if (type.Name.Contains (SymbolKind.PortablePdb.ToString ())) + return SymbolKind.PortablePdb; + if (type.Name.Contains (SymbolKind.NativePdb.ToString ())) + return SymbolKind.NativePdb; + if (type.Name.Contains (SymbolKind.Mdb.ToString ())) + return SymbolKind.Mdb; + + throw new ArgumentException (); } #endif @@ -726,6 +800,29 @@ namespace Mono.Cecil.Cil { ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream); } +#if !PCL + public class DefaultSymbolWriterProvider : ISymbolWriterProvider { + + public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName) + { + var reader = module.SymbolReader; + if (reader == null) + throw new InvalidOperationException (); + + if (module.Image != null && module.Image.HasDebugTables ()) + return null; + + var reader_kind = SymbolProvider.GetSymbolKind (reader.GetType ()); + return SymbolProvider.GetWriterProvider (reader_kind).GetSymbolWriter (module, fileName); + } + + public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream) + { + throw new NotSupportedException (); + } + } +#endif + #endif } @@ -744,6 +841,26 @@ namespace Mono.Cecil { { return assemblyFileName + ".mdb"; } + + public static bool IsPortablePdb (string fileName) + { + using (var file = new FileStream (fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) + return IsPortablePdb (file); + } + + public static bool IsPortablePdb (Stream stream) + { + const uint ppdb_signature = 0x424a5342; + + var position = stream.Position; + try { + var reader = new BinaryReader (stream); + return reader.ReadUInt32 () == ppdb_signature; + } finally { + stream.Position = position; + } + } + } } diff --git a/Mono.Cecil.Metadata/Buffers.cs b/Mono.Cecil.Metadata/Buffers.cs index 5a915e2..0eb0b48 100644 --- a/Mono.Cecil.Metadata/Buffers.cs +++ b/Mono.Cecil.Metadata/Buffers.cs @@ -34,6 +34,8 @@ namespace Mono.Cecil.Metadata { readonly int [] coded_index_sizes = new int [Mixin.CodedIndexCount]; readonly Func<Table, int> counter; + internal uint [] string_offsets; + public override bool IsEmpty { get { return false; } } @@ -81,7 +83,7 @@ namespace Mono.Cecil.Metadata { public void WriteString (uint @string) { - WriteBySize (@string, large_string); + WriteBySize (string_offsets [@string], large_string); } public void WriteBlob (uint blob) @@ -299,7 +301,7 @@ namespace Mono.Cecil.Metadata { class StringHeapBuffer : HeapBuffer { - readonly Dictionary<string, uint> strings = new Dictionary<string, uint> (StringComparer.Ordinal); + protected Dictionary<string, uint> strings = new Dictionary<string, uint> (StringComparer.Ordinal); public sealed override bool IsEmpty { get { return length <= 1; } @@ -311,23 +313,87 @@ namespace Mono.Cecil.Metadata { WriteByte (0); } - public uint GetStringIndex (string @string) + public virtual uint GetStringIndex (string @string) { uint index; if (strings.TryGetValue (@string, out index)) return index; - index = (uint) base.position; - WriteString (@string); + index = (uint) strings.Count + 1; strings.Add (@string, index); return index; } + public uint [] WriteStrings () + { + var sorted = SortStrings (strings); + strings = null; + + // Add 1 for empty string whose index and offset are both 0 + var string_offsets = new uint [sorted.Count + 1]; + string_offsets [0] = 0; + + // Find strings that can be folded + var previous = string.Empty; + foreach (var entry in sorted) { + var @string = entry.Key; + var index = entry.Value; + var position = base.position; + + if (previous.EndsWith (@string, StringComparison.Ordinal) && !IsLowSurrogateChar (entry.Key [0])) { + // Map over the tail of prev string. Watch for null-terminator of prev string. + string_offsets [index] = (uint) (position - (Encoding.UTF8.GetByteCount (entry.Key) + 1)); + } else { + string_offsets [index] = (uint) position; + WriteString (@string); + } + + previous = entry.Key; + } + + return string_offsets; + } + + static List<KeyValuePair<string, uint>> SortStrings (Dictionary<string, uint> strings) + { + var sorted = new List<KeyValuePair<string, uint>> (strings); + sorted.Sort (new SuffixSort ()); + return sorted; + } + + static bool IsLowSurrogateChar (int c) + { + return unchecked((uint)(c - 0xDC00)) <= 0xDFFF - 0xDC00; + } + protected virtual void WriteString (string @string) { WriteBytes (Encoding.UTF8.GetBytes (@string)); WriteByte (0); } + + // Sorts strings such that a string is followed immediately by all strings + // that are a suffix of it. + private class SuffixSort : IComparer<KeyValuePair<string, uint>> { + + public int Compare(KeyValuePair<string, uint> xPair, KeyValuePair<string, uint> yPair) + { + var x = xPair.Key; + var y = yPair.Key; + + for (int i = x.Length - 1, j = y.Length - 1; i >= 0 & j >= 0; i--, j--) { + if (x [i] < y [j]) { + return -1; + } + + if (x [i] > y [j]) { + return +1; + } + } + + return y.Length.CompareTo (x.Length); + } + } } sealed class BlobHeapBuffer : HeapBuffer { @@ -365,6 +431,18 @@ namespace Mono.Cecil.Metadata { sealed class UserStringHeapBuffer : StringHeapBuffer { + public override uint GetStringIndex (string @string) + { + uint index; + if (strings.TryGetValue (@string, out index)) + return index; + + index = (uint) base.position; + WriteString (@string); + strings.Add (@string, index); + return index; + } + protected override void WriteString (string @string) { WriteCompressedUInt32 ((uint) @string.Length * 2 + 1); diff --git a/Mono.Cecil/AssemblyNameReference.cs b/Mono.Cecil/AssemblyNameReference.cs index fbbe67a..f5d47ce 100644 --- a/Mono.Cecil/AssemblyNameReference.cs +++ b/Mono.Cecil/AssemblyNameReference.cs @@ -238,8 +238,7 @@ namespace Mono.Cecil { public AssemblyNameReference (string name, Version version) { - if (name == null) - throw new ArgumentNullException ("name"); + Mixin.CheckName (name); this.name = name; this.version = Mixin.CheckVersion (version); diff --git a/Mono.Cecil/AssemblyReader.cs b/Mono.Cecil/AssemblyReader.cs index f9b84bb..5482153 100644 --- a/Mono.Cecil/AssemblyReader.cs +++ b/Mono.Cecil/AssemblyReader.cs @@ -99,7 +99,7 @@ namespace Mono.Cecil { #if !PCL if (symbol_reader_provider == null && parameters.ReadSymbols) - symbol_reader_provider = SymbolProvider.GetPlatformReaderProvider (); + symbol_reader_provider = new DefaultSymbolReaderProvider (); #endif if (symbol_reader_provider != null) { @@ -115,7 +115,8 @@ namespace Mono.Cecil { var reader = symbol_reader_provider.GetSymbolReader (module, parameters.SymbolStream); #endif - module.ReadSymbols (reader); + if (reader != null) + module.ReadSymbols (reader); } if (module.Image.HasDebugTables ()) diff --git a/Mono.Cecil/AssemblyWriter.cs b/Mono.Cecil/AssemblyWriter.cs index 7841240..ec7e4d5 100644 --- a/Mono.Cecil/AssemblyWriter.cs +++ b/Mono.Cecil/AssemblyWriter.cs @@ -93,7 +93,7 @@ namespace Mono.Cecil { var symbol_writer_provider = parameters.SymbolWriterProvider; #if !PCL && !NET_CORE if (symbol_writer_provider == null && parameters.WriteSymbols) - symbol_writer_provider = SymbolProvider.GetPlatformWriterProvider (); + symbol_writer_provider = new DefaultSymbolWriterProvider (); #endif var symbol_writer = GetSymbolWriter (module, fq_name, symbol_writer_provider, parameters); @@ -1007,6 +1007,7 @@ namespace Mono.Cecil { { BuildModule (); + table_heap.string_offsets = string_heap.WriteStrings (); table_heap.WriteTableHeap (); } diff --git a/Mono.Cecil/BaseAssemblyResolver.cs b/Mono.Cecil/BaseAssemblyResolver.cs index 5390d66..10cf3e5 100644 --- a/Mono.Cecil/BaseAssemblyResolver.cs +++ b/Mono.Cecil/BaseAssemblyResolver.cs @@ -105,10 +105,8 @@ namespace Mono.Cecil { public virtual AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters) { - if (name == null) - throw new ArgumentNullException ("name"); - if (parameters == null) - parameters = new ReaderParameters (); + Mixin.CheckName (name); + Mixin.CheckParameters (parameters); var assembly = SearchDirectory (name, directories, parameters); if (assembly != null) diff --git a/Mono.Cecil/CustomAttribute.cs b/Mono.Cecil/CustomAttribute.cs index 11dcb89..5e33667 100644 --- a/Mono.Cecil/CustomAttribute.cs +++ b/Mono.Cecil/CustomAttribute.cs @@ -200,15 +200,4 @@ namespace Mono.Cecil { }); } } - - static partial class Mixin { - - public static void CheckName (string name) - { - if (name == null) - throw new ArgumentNullException ("name"); - if (name.Length == 0) - throw new ArgumentException ("Empty name"); - } - } } diff --git a/Mono.Cecil/DefaultAssemblyResolver.cs b/Mono.Cecil/DefaultAssemblyResolver.cs index d33b563..d121388 100644 --- a/Mono.Cecil/DefaultAssemblyResolver.cs +++ b/Mono.Cecil/DefaultAssemblyResolver.cs @@ -26,8 +26,7 @@ namespace Mono.Cecil { public override AssemblyDefinition Resolve (AssemblyNameReference name) { - if (name == null) - throw new ArgumentNullException ("name"); + Mixin.CheckName (name); AssemblyDefinition assembly; if (cache.TryGetValue (name.FullName, out assembly)) diff --git a/Mono.Cecil/EventReference.cs b/Mono.Cecil/EventReference.cs index 925a581..d4df72b 100644 --- a/Mono.Cecil/EventReference.cs +++ b/Mono.Cecil/EventReference.cs @@ -28,9 +28,7 @@ namespace Mono.Cecil { protected EventReference (string name, TypeReference eventType) : base (name) { - if (eventType == null) - throw new ArgumentNullException ("eventType"); - + Mixin.CheckType (eventType, Mixin.Argument.eventType); event_type = eventType; } diff --git a/Mono.Cecil/FieldReference.cs b/Mono.Cecil/FieldReference.cs index f65a300..944c225 100644 --- a/Mono.Cecil/FieldReference.cs +++ b/Mono.Cecil/FieldReference.cs @@ -37,8 +37,7 @@ namespace Mono.Cecil { public FieldReference (string name, TypeReference fieldType) : base (name) { - if (fieldType == null) - throw new ArgumentNullException ("fieldType"); + Mixin.CheckType (fieldType, Mixin.Argument.fieldType); this.field_type = fieldType; this.token = new MetadataToken (TokenType.MemberRef); @@ -47,8 +46,7 @@ namespace Mono.Cecil { public FieldReference (string name, TypeReference fieldType, TypeReference declaringType) : this (name, fieldType) { - if (declaringType == null) - throw new ArgumentNullException("declaringType"); + Mixin.CheckType (declaringType, Mixin.Argument.declaringType); this.DeclaringType = declaringType; } diff --git a/Mono.Cecil/GenericParameter.cs b/Mono.Cecil/GenericParameter.cs index 24024d2..f2997da 100644 --- a/Mono.Cecil/GenericParameter.cs +++ b/Mono.Cecil/GenericParameter.cs @@ -188,8 +188,7 @@ namespace Mono.Cecil { internal GenericParameter (int position, GenericParameterType type, ModuleDefinition module) : base (string.Empty, string.Empty) { - if (module == null) - throw new ArgumentNullException (); + Mixin.CheckModule (module); this.position = position; this.type = type; diff --git a/Mono.Cecil/Import.cs b/Mono.Cecil/Import.cs index 846f6d5..8d8b8f7 100644 --- a/Mono.Cecil/Import.cs +++ b/Mono.Cecil/Import.cs @@ -740,7 +740,7 @@ namespace Mono.Cecil { public static void CheckModule (ModuleDefinition module) { if (module == null) - throw new ArgumentNullException ("module"); + throw new ArgumentNullException (Argument.module.ToString ()); } public static bool TryGetAssemblyNameReference (this ModuleDefinition module, AssemblyNameReference name_reference, out AssemblyNameReference assembly_reference) diff --git a/Mono.Cecil/MetadataResolver.cs b/Mono.Cecil/MetadataResolver.cs index 95b0e30..cd3c354 100644 --- a/Mono.Cecil/MetadataResolver.cs +++ b/Mono.Cecil/MetadataResolver.cs @@ -87,8 +87,7 @@ namespace Mono.Cecil { public virtual TypeDefinition Resolve (TypeReference type) { - if (type == null) - throw new ArgumentNullException ("type"); + Mixin.CheckType (type); type = type.GetElementType (); @@ -159,8 +158,7 @@ namespace Mono.Cecil { public virtual FieldDefinition Resolve (FieldReference field) { - if (field == null) - throw new ArgumentNullException ("field"); + Mixin.CheckField (field); var type = Resolve (field.DeclaringType); if (type == null) @@ -207,8 +205,7 @@ namespace Mono.Cecil { public virtual MethodDefinition Resolve (MethodReference method) { - if (method == null) - throw new ArgumentNullException ("method"); + Mixin.CheckMethod (method); var type = Resolve (method.DeclaringType); if (type == null) diff --git a/Mono.Cecil/MethodReference.cs b/Mono.Cecil/MethodReference.cs index 8e92479..89ee6a7 100644 --- a/Mono.Cecil/MethodReference.cs +++ b/Mono.Cecil/MethodReference.cs @@ -144,8 +144,7 @@ namespace Mono.Cecil { public MethodReference (string name, TypeReference returnType) : base (name) { - if (returnType == null) - throw new ArgumentNullException ("returnType"); + Mixin.CheckType (returnType, Mixin.Argument.returnType); this.return_type = new MethodReturnType (this); this.return_type.ReturnType = returnType; @@ -155,8 +154,7 @@ namespace Mono.Cecil { public MethodReference (string name, TypeReference returnType, TypeReference declaringType) : this (name, returnType) { - if (declaringType == null) - throw new ArgumentNullException ("declaringType"); + Mixin.CheckType (declaringType, Mixin.Argument.declaringType); this.DeclaringType = declaringType; } diff --git a/Mono.Cecil/MethodSpecification.cs b/Mono.Cecil/MethodSpecification.cs index c0f3a86..040be6e 100644 --- a/Mono.Cecil/MethodSpecification.cs +++ b/Mono.Cecil/MethodSpecification.cs @@ -70,8 +70,7 @@ namespace Mono.Cecil { internal MethodSpecification (MethodReference method) { - if (method == null) - throw new ArgumentNullException ("method"); + Mixin.CheckMethod (method); this.method = method; this.token = new MetadataToken (TokenType.MethodSpec); diff --git a/Mono.Cecil/Modifiers.cs b/Mono.Cecil/Modifiers.cs index 7575ec1..9c50f0e 100644 --- a/Mono.Cecil/Modifiers.cs +++ b/Mono.Cecil/Modifiers.cs @@ -56,7 +56,9 @@ namespace Mono.Cecil { public OptionalModifierType (TypeReference modifierType, TypeReference type) : base (type) { - Mixin.CheckModifier (modifierType, type); + if (modifierType == null) + throw new ArgumentNullException (Mixin.Argument.modifierType.ToString ()); + Mixin.CheckType (type); this.modifier_type = modifierType; this.etype = MD.ElementType.CModOpt; } @@ -99,21 +101,12 @@ namespace Mono.Cecil { public RequiredModifierType (TypeReference modifierType, TypeReference type) : base (type) { - Mixin.CheckModifier (modifierType, type); + if (modifierType == null) + throw new ArgumentNullException (Mixin.Argument.modifierType.ToString ()); + Mixin.CheckType (type); this.modifier_type = modifierType; this.etype = MD.ElementType.CModReqD; } } - - static partial class Mixin { - - public static void CheckModifier (TypeReference modifierType, TypeReference type) - { - if (modifierType == null) - throw new ArgumentNullException ("modifierType"); - if (type == null) - throw new ArgumentNullException ("type"); - } - } } diff --git a/Mono.Cecil/ModuleDefinition.cs b/Mono.Cecil/ModuleDefinition.cs index 0d799c8..2036986 100644 --- a/Mono.Cecil/ModuleDefinition.cs +++ b/Mono.Cecil/ModuleDefinition.cs @@ -88,10 +88,12 @@ namespace Mono.Cecil { set { symbol_reader_provider = value; } } +#if !PCL public bool ReadSymbols { get { return read_symbols; } set { read_symbols = value; } } +#endif public bool ReadWrite { get { return read_write; } @@ -234,10 +236,13 @@ namespace Mono.Cecil { set { symbol_writer_provider = value; } } +#if !PCL public bool WriteSymbols { get { return write_symbols; } set { write_symbols = value; } } +#endif + #if !PCL && !NET_CORE public SR.StrongNameKeyPair StrongNameKeyPair { get { return key_pair; } @@ -615,7 +620,7 @@ namespace Mono.Cecil { public bool HasTypeReference (string scope, string fullName) { - CheckFullName (fullName); + Mixin.CheckFullName (fullName); if (!HasImage) return false; @@ -630,7 +635,7 @@ namespace Mono.Cecil { public bool TryGetTypeReference (string scope, string fullName, out TypeReference type) { - CheckFullName (fullName); + Mixin.CheckFullName (fullName); if (!HasImage) { type = null; @@ -678,7 +683,7 @@ namespace Mono.Cecil { public TypeDefinition GetType (string fullName) { - CheckFullName (fullName); + Mixin.CheckFullName (fullName); var position = fullName.IndexOf ('/'); if (position > 0) @@ -714,14 +719,6 @@ namespace Mono.Cecil { } } - static void CheckFullName (string fullName) - { - if (fullName == null) - throw new ArgumentNullException ("fullName"); - if (fullName.Length == 0) - throw new ArgumentException (); - } - TypeDefinition GetNestedType (string fullname) { var names = fullname.Split ('/'); @@ -1089,10 +1086,7 @@ namespace Mono.Cecil { if (string.IsNullOrEmpty (file_name)) throw new InvalidOperationException (); - var provider = SymbolProvider.GetPlatformReaderProvider (); - if (provider == null) - throw new InvalidOperationException (); - + var provider = new DefaultSymbolReaderProvider (throwIfNoSymbol: true); ReadSymbols (provider.GetSymbolReader (this, file_name)); } #endif @@ -1220,18 +1214,53 @@ namespace Mono.Cecil { static partial class Mixin { + public enum Argument { + name, + fileName, + fullName, + stream, + type, + method, + field, + parameters, + module, + modifierType, + eventType, + fieldType, + declaringType, + returnType, + propertyType, + interfaceType, + } + + public static void CheckName (object name) + { + if (name == null) + throw new ArgumentNullException (Argument.name.ToString ()); + } + + public static void CheckName (string name) + { + if (string.IsNullOrEmpty (name)) + throw new ArgumentNullOrEmptyException (Argument.name.ToString ()); + } + public static void CheckFileName (string fileName) { - if (fileName == null) - throw new ArgumentNullException ("fileName"); - if (fileName.Length == 0) - throw new ArgumentException (); + if (string.IsNullOrEmpty (fileName)) + throw new ArgumentNullOrEmptyException (Argument.fileName.ToString ()); + } + + public static void CheckFullName (string fullName) + { + if (string.IsNullOrEmpty (fullName)) + throw new ArgumentNullOrEmptyException (Argument.fullName.ToString ()); } public static void CheckStream (object stream) { if (stream == null) - throw new ArgumentNullException ("stream"); + throw new ArgumentNullException (Argument.stream.ToString ()); } public static void CheckWriteSeek (Stream stream) @@ -1251,19 +1280,25 @@ namespace Mono.Cecil { public static void CheckType (object type) { if (type == null) - throw new ArgumentNullException ("type"); + throw new ArgumentNullException (Argument.type.ToString ()); + } + + public static void CheckType (object type, Argument argument) + { + if (type == null) + throw new ArgumentNullException (argument.ToString ()); } public static void CheckField (object field) { if (field == null) - throw new ArgumentNullException ("field"); + throw new ArgumentNullException (Argument.field.ToString ()); } public static void CheckMethod (object method) { if (method == null) - throw new ArgumentNullException ("method"); + throw new ArgumentNullException (Argument.method.ToString ()); } #endif @@ -1271,7 +1306,7 @@ namespace Mono.Cecil { public static void CheckParameters (object parameters) { if (parameters == null) - throw new ArgumentNullException ("parameters"); + throw new ArgumentNullException (Argument.parameters.ToString ()); } public static bool HasImage (this ModuleDefinition self) diff --git a/Mono.Cecil/PropertyReference.cs b/Mono.Cecil/PropertyReference.cs index 4b827cd..2434d0f 100644 --- a/Mono.Cecil/PropertyReference.cs +++ b/Mono.Cecil/PropertyReference.cs @@ -30,8 +30,7 @@ namespace Mono.Cecil { internal PropertyReference (string name, TypeReference propertyType) : base (name) { - if (propertyType == null) - throw new ArgumentNullException ("propertyType"); + Mixin.CheckType (propertyType, Mixin.Argument.propertyType); property_type = propertyType; } diff --git a/Mono.Cecil/TypeDefinition.cs b/Mono.Cecil/TypeDefinition.cs index 62f65a5..435beaf 100644 --- a/Mono.Cecil/TypeDefinition.cs +++ b/Mono.Cecil/TypeDefinition.cs @@ -528,8 +528,7 @@ namespace Mono.Cecil { public InterfaceImplementation (TypeReference interfaceType) { - if (interfaceType == null) - throw new ArgumentNullException ("interfaceType"); + Mixin.CheckType (interfaceType, Mixin.Argument.interfaceType); this.interface_type = interfaceType; this.token = new MetadataToken (TokenType.InterfaceImpl); diff --git a/Mono.Cecil/TypeSpecification.cs b/Mono.Cecil/TypeSpecification.cs index d26be5b..16e0cab 100644 --- a/Mono.Cecil/TypeSpecification.cs +++ b/Mono.Cecil/TypeSpecification.cs @@ -65,13 +65,4 @@ namespace Mono.Cecil { return element_type.GetElementType (); } } - - static partial class Mixin { - - public static void CheckType (TypeReference type) - { - if (type == null) - throw new ArgumentNullException ("type"); - } - } } diff --git a/Mono/Empty.cs b/Mono/Empty.cs index 14589cc..de28e65 100644 --- a/Mono/Empty.cs +++ b/Mono/Empty.cs @@ -17,6 +17,14 @@ namespace Mono { public static readonly T [] Array = new T [0]; } + + class ArgumentNullOrEmptyException : ArgumentException { + + public ArgumentNullOrEmptyException (string paramName) + : base ("Argument null or empty", paramName) + { + } + } } namespace Mono.Cecil { diff --git a/Test/Mono.Cecil.Tests.csproj b/Test/Mono.Cecil.Tests.csproj index 993a1c6..9277d6a 100644 --- a/Test/Mono.Cecil.Tests.csproj +++ b/Test/Mono.Cecil.Tests.csproj @@ -10,6 +10,14 @@ <Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project> <Name>Mono.Cecil</Name> </ProjectReference> + <ProjectReference Include="..\symbols\mdb\Mono.Cecil.Mdb.csproj"> + <Project>{8559dd7f-a16f-46d0-a05a-9139faeba8fd}</Project> + <Name>Mono.Cecil.Mdb</Name> + </ProjectReference> + <ProjectReference Include="..\symbols\pdb\Mono.Cecil.Pdb.csproj"> + <Project>{63e6915c-7ea4-4d76-ab28-0d7191eea626}</Project> + <Name>Mono.Cecil.Pdb</Name> + </ProjectReference> </ItemGroup> <ItemGroup> <Compile Include="..\ProjectInfo.cs" /> diff --git a/Test/Mono.Cecil.Tests/SymbolTests.cs b/Test/Mono.Cecil.Tests/SymbolTests.cs new file mode 100644 index 0000000..d9b85f1 --- /dev/null +++ b/Test/Mono.Cecil.Tests/SymbolTests.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; + +using NUnit.Framework; + +using Mono.Cecil.Cil; +using Mono.Cecil.Mdb; +using Mono.Cecil.Pdb; + +namespace Mono.Cecil.Tests { + + [TestFixture] + public class SymbolTests : BaseTestFixture { + + [Test] + public void DefaultPdb () + { + IgnoreOnMono (); + + TestModule ("libpdb.dll", module => { + Assert.IsTrue (module.HasSymbols); + Assert.AreEqual (typeof (NativePdbReader), module.SymbolReader.GetType ()); + }, symbolReaderProvider: typeof (DefaultSymbolReaderProvider), symbolWriterProvider: typeof (DefaultSymbolWriterProvider)); + } + + [Test] + public void DefaultMdb () + { + TestModule ("libmdb.dll", module => { + Assert.IsTrue (module.HasSymbols); + Assert.AreEqual (typeof (MdbReader), module.SymbolReader.GetType ()); + }, symbolReaderProvider: typeof (DefaultSymbolReaderProvider), symbolWriterProvider: typeof (DefaultSymbolWriterProvider)); + } + + [Test] + public void DefaultPortablePdb () + { + TestModule ("PdbTarget.exe", module => { + Assert.IsTrue (module.HasSymbols); + Assert.AreEqual (typeof (PortablePdbReader), module.SymbolReader.GetType ()); + }, symbolReaderProvider: typeof (DefaultSymbolReaderProvider), symbolWriterProvider: typeof (DefaultSymbolWriterProvider)); + } + + [Test] + public void DefaultEmbeddedPortablePdb () + { + TestModule ("EmbeddedPdbTarget.exe", module => { + Assert.IsTrue (module.HasSymbols); + Assert.AreEqual (typeof (PortablePdbReader), module.SymbolReader.GetType ()); + }, symbolReaderProvider: typeof (DefaultSymbolReaderProvider), symbolWriterProvider: typeof (DefaultSymbolWriterProvider), verify: !Platform.OnMono); + } + } +} diff --git a/Test/Resources/assemblies/libmdb.dll b/Test/Resources/assemblies/libmdb.dll Binary files differnew file mode 100644 index 0000000..545c2c0 --- /dev/null +++ b/Test/Resources/assemblies/libmdb.dll diff --git a/Test/Resources/assemblies/libmdb.dll.mdb b/Test/Resources/assemblies/libmdb.dll.mdb Binary files differnew file mode 100644 index 0000000..76b56d4 --- /dev/null +++ b/Test/Resources/assemblies/libmdb.dll.mdb diff --git a/Test/Resources/assemblies/libpdb.dll b/Test/Resources/assemblies/libpdb.dll Binary files differnew file mode 100644 index 0000000..29dbf08 --- /dev/null +++ b/Test/Resources/assemblies/libpdb.dll diff --git a/Test/Resources/assemblies/libpdb.pdb b/Test/Resources/assemblies/libpdb.pdb Binary files differnew file mode 100644 index 0000000..dd35d1b --- /dev/null +++ b/Test/Resources/assemblies/libpdb.pdb diff --git a/symbols/pdb/Mono.Cecil.Pdb/PdbReader.cs b/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs index 317a496..4ad1bc4 100644 --- a/symbols/pdb/Mono.Cecil.Pdb/PdbReader.cs +++ b/symbols/pdb/Mono.Cecil.Pdb/NativePdbReader.cs @@ -20,7 +20,7 @@ using Mono.Cecil.Cil; namespace Mono.Cecil.Pdb { - public class PdbReader : ISymbolReader { + public class NativePdbReader : ISymbolReader { int age; Guid guid; @@ -29,7 +29,7 @@ namespace Mono.Cecil.Pdb { readonly Dictionary<string, Document> documents = new Dictionary<string, Document> (); readonly Dictionary<uint, PdbFunction> functions = new Dictionary<uint, PdbFunction> (); - internal PdbReader (Disposable<Stream> file) + internal NativePdbReader (Disposable<Stream> file) { this.pdb_file = file; } diff --git a/symbols/pdb/Mono.Cecil.Pdb/PdbWriter.cs b/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs index 553ef2f..28df637 100644 --- a/symbols/pdb/Mono.Cecil.Pdb/PdbWriter.cs +++ b/symbols/pdb/Mono.Cecil.Pdb/NativePdbWriter.cs @@ -19,13 +19,13 @@ using Mono.Collections.Generic; namespace Mono.Cecil.Pdb { - public class PdbWriter : Cil.ISymbolWriter { + public class NativePdbWriter : Cil.ISymbolWriter { readonly ModuleDefinition module; readonly SymWriter writer; readonly Dictionary<string, SymDocumentWriter> documents; - internal PdbWriter (ModuleDefinition module, SymWriter writer) + internal NativePdbWriter (ModuleDefinition module, SymWriter writer) { this.module = module; this.writer = writer; diff --git a/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs b/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs index c397398..ced9729 100644 --- a/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs +++ b/symbols/pdb/Mono.Cecil.Pdb/PdbHelper.cs @@ -22,7 +22,7 @@ namespace Mono.Cecil.Pdb { Mixin.CheckModule (module); Mixin.CheckFileName (fileName); - return new PdbReader (Disposable.Owned (File.OpenRead (Mixin.GetPdbFileName (fileName)) as Stream)); + return new NativePdbReader (Disposable.Owned (File.OpenRead (Mixin.GetPdbFileName (fileName)) as Stream)); } public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream) @@ -30,7 +30,7 @@ namespace Mono.Cecil.Pdb { Mixin.CheckModule (module); Mixin.CheckStream (symbolStream); - return new PdbReader (Disposable.NotOwned (symbolStream)); + return new NativePdbReader (Disposable.NotOwned (symbolStream)); } } @@ -41,7 +41,7 @@ namespace Mono.Cecil.Pdb { Mixin.CheckModule (module); Mixin.CheckFileName (fileName); - return IsPortablePdb (Mixin.GetPdbFileName (fileName)) + return Mixin.IsPortablePdb (Mixin.GetPdbFileName (fileName)) ? new PortablePdbReaderProvider ().GetSymbolReader (module, fileName) : new NativePdbReaderProvider ().GetSymbolReader (module, fileName); } @@ -52,29 +52,10 @@ namespace Mono.Cecil.Pdb { Mixin.CheckStream (symbolStream); Mixin.CheckReadSeek (symbolStream); - return IsPortablePdb (symbolStream) + return Mixin.IsPortablePdb (symbolStream) ? new PortablePdbReaderProvider ().GetSymbolReader (module, symbolStream) : new NativePdbReaderProvider ().GetSymbolReader (module, symbolStream); } - - static bool IsPortablePdb (string fileName) - { - using (var file = new FileStream (fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) - return IsPortablePdb (file); - } - - static bool IsPortablePdb (Stream stream) - { - const uint ppdb_signature = 0x424a5342; - - var position = stream.Position; - try { - var reader = new BinaryReader (stream); - return reader.ReadUInt32 () == ppdb_signature; - } finally { - stream.Position = position; - } - } } #if !READ_ONLY @@ -86,7 +67,7 @@ namespace Mono.Cecil.Pdb { Mixin.CheckModule (module); Mixin.CheckFileName (fileName); - return new PdbWriter (module, CreateWriter (module, Mixin.GetPdbFileName (fileName))); + return new NativePdbWriter (module, CreateWriter (module, Mixin.GetPdbFileName (fileName))); } static SymWriter CreateWriter (ModuleDefinition module, string pdb) |