5
// Jb Evain (jbevain@gmail.com)
7
// Copyright (c) 2008 - 2010 Jb Evain
9
// Permission is hereby granted, free of charge, to any person obtaining
10
// a copy of this software and associated documentation files (the
11
// "Software"), to deal in the Software without restriction, including
12
// without limitation the rights to use, copy, modify, merge, publish,
13
// distribute, sublicense, and/or sell copies of the Software, and to
14
// permit persons to whom the Software is furnished to do so, subject to
15
// the following conditions:
17
// The above copyright notice and this permission notice shall be
18
// included in all copies or substantial portions of the Software.
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30
using System.Collections.Generic;
32
using SR = System.Reflection;
35
using Mono.Cecil.Metadata;
37
using Mono.Collections.Generic;
39
namespace Mono.Cecil {
41
public enum ReadingMode {
46
public sealed class ReaderParameters {
48
ReadingMode reading_mode;
49
IAssemblyResolver assembly_resolver;
51
ISymbolReaderProvider symbol_reader_provider;
54
public ReadingMode ReadingMode {
55
get { return reading_mode; }
56
set { reading_mode = value; }
59
public IAssemblyResolver AssemblyResolver {
60
get { return assembly_resolver; }
61
set { assembly_resolver = value; }
64
public Stream SymbolStream {
65
get { return symbol_stream; }
66
set { symbol_stream = value; }
69
public ISymbolReaderProvider SymbolReaderProvider {
70
get { return symbol_reader_provider; }
71
set { symbol_reader_provider = value; }
74
public bool ReadSymbols {
75
get { return read_symbols; }
76
set { read_symbols = value; }
79
public ReaderParameters ()
80
: this (ReadingMode.Deferred)
84
public ReaderParameters (ReadingMode readingMode)
86
this.reading_mode = readingMode;
92
public sealed class ModuleParameters {
95
TargetRuntime runtime;
96
TargetArchitecture architecture;
97
IAssemblyResolver assembly_resolver;
99
public ModuleKind Kind {
101
set { kind = value; }
104
public TargetRuntime Runtime {
105
get { return runtime; }
106
set { runtime = value; }
109
public TargetArchitecture Architecture {
110
get { return architecture; }
111
set { architecture = value; }
114
public IAssemblyResolver AssemblyResolver {
115
get { return assembly_resolver; }
116
set { assembly_resolver = value; }
119
public ModuleParameters ()
121
this.kind = ModuleKind.Dll;
122
this.runtime = GetCurrentRuntime ();
123
this.architecture = TargetArchitecture.I386;
126
static TargetRuntime GetCurrentRuntime ()
129
return typeof (object).Assembly.ImageRuntimeVersion.ParseRuntime ();
131
var corlib_version = typeof (object).Assembly.GetName ().Version;
132
switch (corlib_version.Major) {
134
return corlib_version.Minor == 0
135
? TargetRuntime.Net_1_0
136
: TargetRuntime.Net_1_1;
138
return TargetRuntime.Net_2_0;
140
return TargetRuntime.Net_4_0;
142
throw new NotSupportedException ();
148
public sealed class WriterParameters {
150
Stream symbol_stream;
151
ISymbolWriterProvider symbol_writer_provider;
153
#if !SILVERLIGHT && !CF
154
SR.StrongNameKeyPair key_pair;
156
public Stream SymbolStream {
157
get { return symbol_stream; }
158
set { symbol_stream = value; }
161
public ISymbolWriterProvider SymbolWriterProvider {
162
get { return symbol_writer_provider; }
163
set { symbol_writer_provider = value; }
166
public bool WriteSymbols {
167
get { return write_symbols; }
168
set { write_symbols = value; }
170
#if !SILVERLIGHT && !CF
171
public SR.StrongNameKeyPair StrongNameKeyPair {
172
get { return key_pair; }
173
set { key_pair = value; }
180
public sealed class ModuleDefinition : ModuleReference, ICustomAttributeProvider {
182
internal Image Image;
183
internal MetadataSystem MetadataSystem;
184
internal ReadingMode ReadingMode;
185
internal ISymbolReaderProvider SymbolReaderProvider;
186
internal ISymbolReader SymbolReader;
188
internal IAssemblyResolver assembly_resolver;
189
internal TypeSystem type_system;
191
readonly MetadataReader reader;
192
readonly string fq_name;
194
internal ModuleKind kind;
195
TargetRuntime runtime;
196
TargetArchitecture architecture;
197
ModuleAttributes attributes;
200
internal AssemblyDefinition assembly;
201
MethodDefinition entry_point;
204
MetadataImporter importer;
206
Collection<CustomAttribute> custom_attributes;
207
Collection<AssemblyNameReference> references;
208
Collection<ModuleReference> modules;
209
Collection<Resource> resources;
210
Collection<ExportedType> exported_types;
211
TypeDefinitionCollection types;
214
get { return kind != ModuleKind.NetModule; }
217
public ModuleKind Kind {
219
set { kind = value; }
222
public TargetRuntime Runtime {
223
get { return runtime; }
224
set { runtime = value; }
227
public TargetArchitecture Architecture {
228
get { return architecture; }
229
set { architecture = value; }
232
public ModuleAttributes Attributes {
233
get { return attributes; }
234
set { attributes = value; }
237
public string FullyQualifiedName {
238
get { return fq_name; }
243
set { mvid = value; }
246
internal bool HasImage {
247
get { return Image != null; }
250
public bool HasSymbols {
251
get { return SymbolReader != null; }
254
public override MetadataScopeType MetadataScopeType {
255
get { return MetadataScopeType.ModuleDefinition; }
258
public AssemblyDefinition Assembly {
259
get { return assembly; }
263
internal MetadataImporter MetadataImporter {
264
get { return importer ?? (importer = new MetadataImporter (this)); }
268
public IAssemblyResolver AssemblyResolver {
269
get { return assembly_resolver; }
272
public TypeSystem TypeSystem {
273
get { return type_system ?? (type_system = TypeSystem.CreateTypeSystem (this)); }
276
public bool HasAssemblyReferences {
278
if (references != null)
279
return references.Count > 0;
281
return HasImage && Image.HasTable (Table.AssemblyRef);
285
public Collection<AssemblyNameReference> AssemblyReferences {
287
if (references != null)
291
return references = Read (this, (_, reader) => reader.ReadAssemblyReferences ());
293
return references = new Collection<AssemblyNameReference> ();
297
public bool HasModuleReferences {
300
return modules.Count > 0;
302
return HasImage && Image.HasTable (Table.ModuleRef);
306
public Collection<ModuleReference> ModuleReferences {
312
return modules = Read (this, (_, reader) => reader.ReadModuleReferences ());
314
return modules = new Collection<ModuleReference> ();
318
public bool HasResources {
320
if (resources != null)
321
return resources.Count > 0;
324
return Image.HasTable (Table.ManifestResource) || Read (this, (_, reader) => reader.HasFileResource ());
330
public Collection<Resource> Resources {
332
if (resources != null)
336
return resources = Read (this, (_, reader) => reader.ReadResources ());
338
return resources = new Collection<Resource> ();
342
public bool HasCustomAttributes {
344
if (custom_attributes != null)
345
return custom_attributes.Count > 0;
347
return this.GetHasCustomAttributes (this);
351
public Collection<CustomAttribute> CustomAttributes {
352
get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (this)); }
355
public bool HasTypes {
358
return types.Count > 0;
360
return HasImage && Image.HasTable (Table.TypeDef);
364
public Collection<TypeDefinition> Types {
370
return types = Read (this, (_, reader) => reader.ReadTypes ());
372
return types = new TypeDefinitionCollection (this);
376
public bool HasExportedTypes {
378
if (exported_types != null)
379
return exported_types.Count > 0;
381
return HasImage && Image.HasTable (Table.ExportedType);
385
public Collection<ExportedType> ExportedTypes {
387
if (exported_types != null)
388
return exported_types;
391
return exported_types = Read (this, (_, reader) => reader.ReadExportedTypes ());
393
return exported_types = new Collection<ExportedType> ();
397
public MethodDefinition EntryPoint {
399
if (entry_point != null)
403
return entry_point = Read (this, (_, reader) => reader.ReadEntryPoint ());
405
return entry_point = null;
407
set { entry_point = value; }
410
internal ModuleDefinition ()
412
this.MetadataSystem = new MetadataSystem ();
413
this.token = new MetadataToken (TokenType.Module, 1);
414
this.assembly_resolver = GlobalAssemblyResolver.Instance;
417
internal ModuleDefinition (Image image)
421
this.kind = image.Kind;
422
this.runtime = image.Runtime;
423
this.architecture = image.Architecture;
424
this.attributes = image.Attributes;
425
this.fq_name = image.FileName;
427
this.reader = new MetadataReader (this);
430
public bool HasTypeReference (string fullName)
432
return HasTypeReference (string.Empty, fullName);
435
public bool HasTypeReference (string scope, string fullName)
437
CheckFullName (fullName);
442
return Read (this, (_, reader) => reader.GetTypeReference (scope, fullName) != null);
445
public bool TryGetTypeReference (string fullName, out TypeReference type)
447
return TryGetTypeReference (string.Empty, fullName, out type);
450
public bool TryGetTypeReference (string scope, string fullName, out TypeReference type)
452
CheckFullName (fullName);
459
return (type = Read (this, (_, reader) => reader.GetTypeReference (scope, fullName))) != null;
462
public IEnumerable<TypeReference> GetTypeReferences ()
465
return Empty<TypeReference>.Array;
467
return Read (this, (_, reader) => reader.GetTypeReferences ());
470
public IEnumerable<MemberReference> GetMemberReferences ()
473
return Empty<MemberReference>.Array;
475
return Read (this, (_, reader) => reader.GetMemberReferences ());
478
public TypeDefinition GetType (string fullName)
480
CheckFullName (fullName);
482
var position = fullName.IndexOf ('/');
484
return GetNestedType (fullName);
486
return ((TypeDefinitionCollection) this.Types).GetType (fullName);
489
public TypeDefinition GetType (string @namespace, string name)
491
Mixin.CheckName (name);
493
return ((TypeDefinitionCollection) this.Types).GetType (@namespace ?? string.Empty, name);
496
static void CheckFullName (string fullName)
498
if (fullName == null)
499
throw new ArgumentNullException ("fullName");
500
if (fullName.Length == 0)
501
throw new ArgumentException ();
504
TypeDefinition GetNestedType (string fullname)
506
var names = fullname.Split ('/');
507
var type = GetType (names [0]);
512
for (int i = 1; i < names.Length; i++) {
513
var nested_type = type.GetNestedType (names [i]);
514
if (nested_type == null)
523
internal FieldDefinition Resolve (FieldReference field)
525
return MetadataResolver.Resolve (AssemblyResolver, field);
528
internal MethodDefinition Resolve (MethodReference method)
530
return MetadataResolver.Resolve (AssemblyResolver, method);
533
internal TypeDefinition Resolve (TypeReference type)
535
return MetadataResolver.Resolve (AssemblyResolver, type);
540
static void CheckType (object type)
543
throw new ArgumentNullException ("type");
546
static void CheckField (object field)
549
throw new ArgumentNullException ("field");
552
static void CheckMethod (object method)
555
throw new ArgumentNullException ("method");
558
static void CheckContext (IGenericParameterProvider context, ModuleDefinition module)
563
if (context.Module != module)
564
throw new ArgumentException ();
568
public TypeReference Import (Type type)
572
return MetadataImporter.ImportType (type, null, ImportGenericKind.Definition);
575
public TypeReference Import (Type type, TypeReference context)
577
return Import (type, (IGenericParameterProvider) context);
580
public TypeReference Import (Type type, MethodReference context)
582
return Import (type, (IGenericParameterProvider) context);
585
TypeReference Import (Type type, IGenericParameterProvider context)
588
CheckContext (context, this);
590
return MetadataImporter.ImportType (
592
(IGenericContext) context,
594
? ImportGenericKind.Open
595
: ImportGenericKind.Definition);
598
public FieldReference Import (SR.FieldInfo field)
602
return MetadataImporter.ImportField (field, null);
605
public FieldReference Import (SR.FieldInfo field, TypeReference context)
607
return Import (field, (IGenericParameterProvider) context);
610
public FieldReference Import (SR.FieldInfo field, MethodReference context)
612
return Import (field, (IGenericParameterProvider) context);
615
FieldReference Import (SR.FieldInfo field, IGenericParameterProvider context)
618
CheckContext (context, this);
620
return MetadataImporter.ImportField (field, (IGenericContext) context);
623
public MethodReference Import (SR.MethodBase method)
625
CheckMethod (method);
627
return MetadataImporter.ImportMethod (method, null, ImportGenericKind.Definition);
630
public MethodReference Import (SR.MethodBase method, TypeReference context)
632
return Import (method, (IGenericParameterProvider) context);
635
public MethodReference Import (SR.MethodBase method, MethodReference context)
637
return Import (method, (IGenericParameterProvider) context);
640
MethodReference Import (SR.MethodBase method, IGenericParameterProvider context)
642
CheckMethod (method);
643
CheckContext (context, this);
645
return MetadataImporter.ImportMethod (method,
646
(IGenericContext) context,
648
? ImportGenericKind.Open
649
: ImportGenericKind.Definition);
653
public TypeReference Import (TypeReference type)
657
if (type.Module == this)
660
return MetadataImporter.ImportType (type, null);
663
public TypeReference Import (TypeReference type, TypeReference context)
665
return Import (type, (IGenericParameterProvider) context);
668
public TypeReference Import (TypeReference type, MethodReference context)
670
return Import (type, (IGenericParameterProvider) context);
673
TypeReference Import (TypeReference type, IGenericParameterProvider context)
677
if (type.Module == this)
680
CheckContext (context, this);
682
return MetadataImporter.ImportType (type, (IGenericContext) context);
685
public FieldReference Import (FieldReference field)
689
if (field.Module == this)
692
return MetadataImporter.ImportField (field, null);
695
public FieldReference Import (FieldReference field, TypeReference context)
697
return Import (field, (IGenericParameterProvider) context);
700
public FieldReference Import (FieldReference field, MethodReference context)
702
return Import (field, (IGenericParameterProvider) context);
705
FieldReference Import (FieldReference field, IGenericParameterProvider context)
709
if (field.Module == this)
712
CheckContext (context, this);
714
return MetadataImporter.ImportField (field, (IGenericContext) context);
717
public MethodReference Import (MethodReference method)
719
CheckMethod (method);
721
if (method.Module == this)
724
return MetadataImporter.ImportMethod (method, null);
727
public MethodReference Import (MethodReference method, TypeReference context)
729
return Import (method, (IGenericParameterProvider) context);
732
public MethodReference Import (MethodReference method, MethodReference context)
734
return Import (method, (IGenericParameterProvider) context);
737
MethodReference Import (MethodReference method, IGenericParameterProvider context)
739
CheckMethod (method);
741
if (method.Module == this)
744
CheckContext (context, this);
746
return MetadataImporter.ImportMethod (method, (IGenericContext) context);
751
public IMetadataTokenProvider LookupToken (int token)
753
return LookupToken (new MetadataToken ((uint) token));
756
public IMetadataTokenProvider LookupToken (MetadataToken token)
758
return Read (this, (_, reader) => reader.LookupToken (token));
761
internal TRet Read<TItem, TRet> (TItem item, Func<TItem, MetadataReader, TRet> read)
763
var position = reader.position;
764
var context = reader.context;
766
var ret = read (item, reader);
768
reader.position = position;
769
reader.context = context;
774
void ProcessDebugHeader ()
776
if (Image == null || Image.Debug.IsZero)
780
var directory = Image.GetDebugHeader (out header);
782
if (!SymbolReader.ProcessDebugHeader (directory, header))
783
throw new InvalidOperationException ();
788
public static ModuleDefinition CreateModule (string name, ModuleKind kind)
790
return CreateModule (name, new ModuleParameters { Kind = kind });
793
public static ModuleDefinition CreateModule (string name, ModuleParameters parameters)
795
Mixin.CheckName (name);
796
Mixin.CheckParameters (parameters);
798
var module = new ModuleDefinition {
800
kind = parameters.Kind,
801
runtime = parameters.Runtime,
802
architecture = parameters.Architecture,
803
mvid = Guid.NewGuid (),
804
Attributes = ModuleAttributes.ILOnly,
807
if (parameters.AssemblyResolver != null)
808
module.assembly_resolver = parameters.AssemblyResolver;
810
if (parameters.Kind != ModuleKind.NetModule) {
811
var assembly = new AssemblyDefinition ();
812
module.assembly = assembly;
813
module.assembly.Name = new AssemblyNameDefinition (name, new Version (0, 0));
814
assembly.main_module = module;
817
module.Types.Add (new TypeDefinition (string.Empty, "<Module>", TypeAttributes.NotPublic));
824
public void ReadSymbols ()
826
if (string.IsNullOrEmpty (fq_name))
827
throw new InvalidOperationException ();
829
var provider = SymbolProvider.GetPlatformReaderProvider ();
831
SymbolReader = provider.GetSymbolReader (this, fq_name);
833
ProcessDebugHeader ();
836
public void ReadSymbols (ISymbolReader reader)
839
throw new ArgumentNullException ("reader");
841
SymbolReader = reader;
843
ProcessDebugHeader ();
846
public static ModuleDefinition ReadModule (string fileName)
848
return ReadModule (fileName, new ReaderParameters (ReadingMode.Deferred));
851
public static ModuleDefinition ReadModule (Stream stream)
853
return ReadModule (stream, new ReaderParameters (ReadingMode.Deferred));
856
public static ModuleDefinition ReadModule (string fileName, ReaderParameters parameters)
858
using (var stream = GetFileStream (fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) {
859
return ReadModule (stream, parameters);
863
static void CheckStream (object stream)
866
throw new ArgumentNullException ("stream");
869
public static ModuleDefinition ReadModule (Stream stream, ReaderParameters parameters)
871
CheckStream (stream);
872
if (!stream.CanRead || !stream.CanSeek)
873
throw new ArgumentException ();
874
Mixin.CheckParameters (parameters);
876
return ModuleReader.CreateModuleFrom (
877
ImageReader.ReadImageFrom (stream),
881
static Stream GetFileStream (string fileName, FileMode mode, FileAccess access, FileShare share)
883
if (fileName == null)
884
throw new ArgumentNullException ("fileName");
885
if (fileName.Length == 0)
886
throw new ArgumentException ();
888
return new FileStream (fileName, mode, access, share);
893
public void Write (string fileName)
895
Write (fileName, new WriterParameters ());
898
public void Write (Stream stream)
900
Write (stream, new WriterParameters ());
903
public void Write (string fileName, WriterParameters parameters)
905
using (var stream = GetFileStream (fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) {
906
Write (stream, parameters);
910
public void Write (Stream stream, WriterParameters parameters)
912
CheckStream (stream);
913
if (!stream.CanWrite || !stream.CanSeek)
914
throw new ArgumentException ();
915
Mixin.CheckParameters (parameters);
917
ModuleWriter.WriteModuleTo (this, stream, parameters);
924
static partial class Mixin {
926
public static void CheckParameters (object parameters)
928
if (parameters == null)
929
throw new ArgumentNullException ("parameters");
932
public static bool HasImage (this ModuleDefinition self)
934
return self != null && self.HasImage;
937
public static string GetFullyQualifiedName (this Stream self)
940
var file_stream = self as FileStream;
941
if (file_stream == null)
944
return Path.GetFullPath (file_stream.Name);
950
public static TargetRuntime ParseRuntime (this string self)
954
return self [3] == '0'
955
? TargetRuntime.Net_1_0
956
: TargetRuntime.Net_1_1;
958
return TargetRuntime.Net_2_0;
961
return TargetRuntime.Net_4_0;