2 // System.Reflection.Emit/AssemblyBuilder.cs
5 // Paolo Molaro (lupus@ximian.com)
7 // (C) 2001 Ximian, Inc. http://www.ximian.com
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Reflection;
35 using System.Resources;
37 using System.Security.Policy;
38 using System.Runtime.Serialization;
39 using System.Globalization;
40 using System.Runtime.CompilerServices;
41 using System.Collections;
42 using System.Runtime.InteropServices;
43 using System.Security;
44 using System.Security.Cryptography;
45 using System.Security.Permissions;
48 using Mono.Security.Cryptography;
50 namespace System.Reflection.Emit
52 internal enum NativeResourceType
60 internal struct RefEmitPermissionSet {
61 public SecurityAction action;
64 public RefEmitPermissionSet (SecurityAction action, string pset) {
70 internal struct MonoResource {
73 public string filename;
74 public ResourceAttributes attrs;
79 internal struct MonoWin32Resource {
85 public MonoWin32Resource (int res_type, int res_id, int lang_id, byte[] data) {
86 this.res_type = res_type;
88 this.lang_id = lang_id;
93 internal class GenericInstanceKey {
97 internal GenericInstanceKey (Type gtd, Type[] args)
103 static bool IsBoundedVector (Type type) {
104 ArrayType at = type as ArrayType;
106 return at.GetEffectiveRank () == 1;
107 return type.ToString ().EndsWith ("[*]", StringComparison.Ordinal); /*Super uggly hack, SR doesn't allow one to query for it */
110 static bool TypeEquals (Type a, Type b) {
114 if (a.HasElementType) {
115 if (!b.HasElementType)
117 if (!TypeEquals (a.GetElementType (), b.GetElementType ()))
122 int rank = a.GetArrayRank ();
123 if (rank != b.GetArrayRank ())
125 if (rank == 1 && IsBoundedVector (a) != IsBoundedVector (b))
127 } else if (a.IsByRef) {
130 } else if (a.IsPointer) {
137 if (a.IsGenericType) {
138 if (!b.IsGenericType)
140 if (a.IsGenericParameter)
142 if (a.IsGenericParameter) //previous test should have caught it
145 if (a.IsGenericTypeDefinition) {
146 if (!b.IsGenericTypeDefinition)
149 if (b.IsGenericTypeDefinition)
151 if (!TypeEquals (a.GetGenericTypeDefinition (), b.GetGenericTypeDefinition ()))
154 Type[] argsA = a.GetGenericArguments ();
155 Type[] argsB = b.GetGenericArguments ();
156 for (int i = 0; i < argsA.Length; ++i) {
157 if (!TypeEquals (argsA [i], argsB [i]))
164 Now only non-generic, non compound types are left. To properly deal with user
165 types we would have to call UnderlyingSystemType, but we let them have their
166 own instantiation as this is MS behavior and mcs (pre C# 4.0, at least) doesn't
167 depend on proper UT canonicalization.
172 public override bool Equals (object obj)
174 GenericInstanceKey other = obj as GenericInstanceKey;
177 if (gtd != other.gtd)
179 for (int i = 0; i < args.Length; ++i) {
181 Type b = other.args [i];
183 We must cannonicalize as much as we can. Using equals means that some resulting types
184 won't have the exact same types as the argument ones.
185 For example, flyweight types used array, pointer and byref will should this behavior.
186 MCS seens to be resilient to this problem so hopefully this won't show up.
188 if (a != b && !a.Equals (b))
194 public override int GetHashCode ()
196 int hash = gtd.GetHashCode ();
197 for (int i = 0; i < args.Length; ++i)
198 hash ^= args [i].GetHashCode ();
205 [ComDefaultInterface (typeof (_AssemblyBuilder))]
206 [ClassInterface (ClassInterfaceType.None)]
207 public sealed class AssemblyBuilder : Assembly, _AssemblyBuilder {
208 #pragma warning disable 169, 414
209 #region Sync with object-internals.h
210 private UIntPtr dynamic_assembly; /* GC-tracked */
211 private MethodInfo entry_point;
212 private ModuleBuilder[] modules;
215 private CustomAttributeBuilder[] cattrs;
216 private MonoResource[] resources;
222 PEFileKinds pekind = PEFileKinds.Dll;
225 Module[] loaded_modules;
226 MonoWin32Resource[] win32_resources;
227 private RefEmitPermissionSet[] permissions_minimum;
228 private RefEmitPermissionSet[] permissions_optional;
229 private RefEmitPermissionSet[] permissions_refused;
230 PortableExecutableKinds peKind;
231 ImageFileMachine machine;
232 bool corlib_internal;
233 Type[] type_forwarders;
236 #pragma warning restore 169, 414
238 internal Type corlib_object_type = typeof (System.Object);
239 internal Type corlib_value_type = typeof (System.ValueType);
240 internal Type corlib_enum_type = typeof (System.Enum);
241 internal Type corlib_void_type = typeof (void);
242 ArrayList resource_writers = null;
243 Win32VersionResource version_res;
246 private Mono.Security.StrongName sn;
247 NativeResourceType native_resource;
248 readonly bool is_compiler_context;
249 string versioninfo_culture;
250 Hashtable generic_instances = new Hashtable ();
252 [MethodImplAttribute(MethodImplOptions.InternalCall)]
253 private static extern void basic_init (AssemblyBuilder ab);
255 /* Keep this in sync with codegen.cs in mcs */
256 private const AssemblyBuilderAccess COMPILER_ACCESS = (AssemblyBuilderAccess) 0x800;
258 internal AssemblyBuilder (AssemblyName n, string directory, AssemblyBuilderAccess access, bool corlib_internal)
260 is_compiler_context = (access & COMPILER_ACCESS) != 0;
262 // remove Mono specific flag to allow enum check to pass
263 access &= ~COMPILER_ACCESS;
266 // only "Run" is supported by Silverlight
267 // however SMCS requires more than this but runs outside the CoreCLR sandbox
268 if (SecurityManager.SecurityEnabled && (access != AssemblyBuilderAccess.Run))
269 throw new ArgumentException ("access");
272 if (!Enum.IsDefined (typeof (AssemblyBuilderAccess), access))
273 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
274 "Argument value {0} is not valid.", (int) access),
278 if ((access & AssemblyBuilderAccess.RunAndCollect) == AssemblyBuilderAccess.RunAndCollect)
279 throw new NotSupportedException ("RunAndCollect not yet supported.");
283 this.access = (uint)access;
284 flags = (uint) n.Flags;
286 // don't call GetCurrentDirectory for Run-only builders (CAS may not like that)
287 if (IsSave && (directory == null || directory.Length == 0)) {
288 dir = Directory.GetCurrentDirectory ();
293 /* Set defaults from n */
294 if (n.CultureInfo != null) {
295 culture = n.CultureInfo.Name;
296 versioninfo_culture = n.CultureInfo.Name;
298 Version v = n.Version;
300 version = v.ToString ();
303 if (n.KeyPair != null) {
304 // full keypair is available (for signing)
305 sn = n.KeyPair.StrongName ();
307 // public key is available (for delay-signing)
308 byte[] pk = n.GetPublicKey ();
309 if ((pk != null) && (pk.Length > 0)) {
310 sn = new Mono.Security.StrongName (pk);
315 flags |= (uint) AssemblyNameFlags.PublicKey;
317 this.corlib_internal = corlib_internal;
319 this.pktoken = new byte[sn.PublicKeyToken.Length * 2];
321 foreach (byte pkb in sn.PublicKeyToken) {
322 string part = pkb.ToString("x2");
323 this.pktoken[pkti++] = (byte)part[0];
324 this.pktoken[pkti++] = (byte)part[1];
331 public override string CodeBase {
333 throw not_supported ();
337 public override MethodInfo EntryPoint {
343 public override string Location {
345 throw not_supported ();
349 /* This is to keep signature compatibility with MS.NET */
350 public override string ImageRuntimeVersion {
352 return base.ImageRuntimeVersion;
357 public override bool ReflectionOnly {
358 get { return base.ReflectionOnly; }
361 public void AddResourceFile (string name, string fileName)
363 AddResourceFile (name, fileName, ResourceAttributes.Public);
366 public void AddResourceFile (string name, string fileName, ResourceAttributes attribute)
368 AddResourceFile (name, fileName, attribute, true);
371 private void AddResourceFile (string name, string fileName, ResourceAttributes attribute, bool fileNeedsToExists)
373 check_name_and_filename (name, fileName, fileNeedsToExists);
375 // Resource files are created/searched under the assembly storage
378 fileName = Path.Combine (dir, fileName);
380 if (resources != null) {
381 MonoResource[] new_r = new MonoResource [resources.Length + 1];
382 System.Array.Copy(resources, new_r, resources.Length);
385 resources = new MonoResource [1];
387 int p = resources.Length - 1;
388 resources [p].name = name;
389 resources [p].filename = fileName;
390 resources [p].attrs = attribute;
394 /// Don't change the method name and parameters order. It is used by mcs
396 internal void AddPermissionRequests (PermissionSet required, PermissionSet optional, PermissionSet refused)
400 throw new InvalidOperationException ("Assembly was already saved.");
402 // required for base Assembly class (so the permissions
403 // can be used even if the assembly isn't saved to disk)
405 _optional = optional;
408 // required to reuse AddDeclarativeSecurity support
409 // already present in the runtime
410 if (required != null) {
411 permissions_minimum = new RefEmitPermissionSet [1];
412 permissions_minimum [0] = new RefEmitPermissionSet (
413 SecurityAction.RequestMinimum, required.ToXml ().ToString ());
415 if (optional != null) {
416 permissions_optional = new RefEmitPermissionSet [1];
417 permissions_optional [0] = new RefEmitPermissionSet (
418 SecurityAction.RequestOptional, optional.ToXml ().ToString ());
420 if (refused != null) {
421 permissions_refused = new RefEmitPermissionSet [1];
422 permissions_refused [0] = new RefEmitPermissionSet (
423 SecurityAction.RequestRefuse, refused.ToXml ().ToString ());
428 internal void EmbedResourceFile (string name, string fileName)
430 EmbedResourceFile (name, fileName, ResourceAttributes.Public);
433 internal void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute)
435 if (resources != null) {
436 MonoResource[] new_r = new MonoResource [resources.Length + 1];
437 System.Array.Copy(resources, new_r, resources.Length);
440 resources = new MonoResource [1];
442 int p = resources.Length - 1;
443 resources [p].name = name;
444 resources [p].attrs = attribute;
446 FileStream s = new FileStream (fileName, FileMode.Open, FileAccess.Read);
448 resources [p].data = new byte [len];
449 s.Read (resources [p].data, 0, (int)len);
456 internal void EmbedResource (string name, byte[] blob, ResourceAttributes attribute)
458 if (resources != null) {
459 MonoResource[] new_r = new MonoResource [resources.Length + 1];
460 System.Array.Copy(resources, new_r, resources.Length);
463 resources = new MonoResource [1];
465 int p = resources.Length - 1;
466 resources [p].name = name;
467 resources [p].attrs = attribute;
468 resources [p].data = blob;
471 internal void AddTypeForwarder (Type t) {
473 throw new ArgumentNullException ("t");
475 throw new ArgumentException ();
477 if (type_forwarders == null) {
478 type_forwarders = new Type [1] { t };
480 Type[] arr = new Type [type_forwarders.Length + 1];
481 Array.Copy (type_forwarders, arr, type_forwarders.Length);
482 arr [type_forwarders.Length] = t;
483 type_forwarders = arr;
487 public ModuleBuilder DefineDynamicModule (string name)
489 return DefineDynamicModule (name, name, false, true);
492 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
494 return DefineDynamicModule (name, name, emitSymbolInfo, true);
497 public ModuleBuilder DefineDynamicModule(string name, string fileName)
499 return DefineDynamicModule (name, fileName, false, false);
502 public ModuleBuilder DefineDynamicModule (string name, string fileName,
505 return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
508 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
510 check_name_and_filename (name, fileName, false);
513 if (Path.GetExtension (fileName) == String.Empty)
514 throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
516 throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
518 throw new InvalidOperationException ("Assembly was already saved.");
521 ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
523 if ((modules != null) && is_module_only)
524 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
526 if (modules != null) {
527 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
528 System.Array.Copy(modules, new_modules, modules.Length);
529 modules = new_modules;
531 modules = new ModuleBuilder [1];
533 modules [modules.Length - 1] = r;
537 [MethodImplAttribute(MethodImplOptions.InternalCall)]
538 private extern Module InternalAddModule (string fileName);
541 * Mono extension to support /addmodule in mcs.
543 internal Module AddModule (string fileName)
545 if (fileName == null)
546 throw new ArgumentNullException (fileName);
548 Module m = InternalAddModule (fileName);
550 if (loaded_modules != null) {
551 Module[] new_modules = new Module [loaded_modules.Length + 1];
552 System.Array.Copy (loaded_modules, new_modules, loaded_modules.Length);
553 loaded_modules = new_modules;
555 loaded_modules = new Module [1];
557 loaded_modules [loaded_modules.Length - 1] = m;
562 public IResourceWriter DefineResource (string name, string description, string fileName)
564 return DefineResource (name, description, fileName, ResourceAttributes.Public);
567 public IResourceWriter DefineResource (string name, string description,
568 string fileName, ResourceAttributes attribute)
570 IResourceWriter writer;
572 // description seems to be ignored
573 AddResourceFile (name, fileName, attribute, false);
574 writer = new ResourceWriter (fileName);
575 if (resource_writers == null)
576 resource_writers = new ArrayList ();
577 resource_writers.Add (writer);
581 private void AddUnmanagedResource (Win32Resource res) {
582 MemoryStream ms = new MemoryStream ();
585 if (win32_resources != null) {
586 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
587 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
588 win32_resources = new_res;
591 win32_resources = new MonoWin32Resource [1];
593 win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
596 [MonoTODO ("Not currently implemenented")]
597 public void DefineUnmanagedResource (byte[] resource)
599 if (resource == null)
600 throw new ArgumentNullException ("resource");
601 if (native_resource != NativeResourceType.None)
602 throw new ArgumentException ("Native resource has already been defined.");
604 // avoid definition of more than one unmanaged resource
605 native_resource = NativeResourceType.Unmanaged;
608 * The format of the argument byte array is not documented
609 * so this method is impossible to implement.
612 throw new NotImplementedException ();
615 public void DefineUnmanagedResource (string resourceFileName)
617 if (resourceFileName == null)
618 throw new ArgumentNullException ("resourceFileName");
619 if (resourceFileName.Length == 0)
620 throw new ArgumentException ("resourceFileName");
621 if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
622 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exists or is a directory.");
623 if (native_resource != NativeResourceType.None)
624 throw new ArgumentException ("Native resource has already been defined.");
626 // avoid definition of more than one unmanaged resource
627 native_resource = NativeResourceType.Unmanaged;
629 using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
630 Win32ResFileReader reader = new Win32ResFileReader (fs);
632 foreach (Win32EncodedResource res in reader.ReadResources ()) {
633 if (res.Name.IsName || res.Type.IsName)
634 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
636 AddUnmanagedResource (res);
641 public void DefineVersionInfoResource ()
643 if (native_resource != NativeResourceType.None)
644 throw new ArgumentException ("Native resource has already been defined.");
646 // avoid definition of more than one unmanaged resource
647 native_resource = NativeResourceType.Assembly;
649 version_res = new Win32VersionResource (1, 0, IsCompilerContext);
652 public void DefineVersionInfoResource (string product, string productVersion,
653 string company, string copyright, string trademark)
655 if (native_resource != NativeResourceType.None)
656 throw new ArgumentException ("Native resource has already been defined.");
658 // avoid definition of more than one unmanaged resource
659 native_resource = NativeResourceType.Explicit;
662 * We can only create the resource later, when the file name and
663 * the binary version is known.
666 version_res = new Win32VersionResource (1, 0, false);
667 version_res.ProductName = product != null ? product : " ";
668 version_res.ProductVersion = productVersion != null ? productVersion : " ";
669 version_res.CompanyName = company != null ? company : " ";
670 version_res.LegalCopyright = copyright != null ? copyright : " ";
671 version_res.LegalTrademarks = trademark != null ? trademark : " ";
675 * Mono extension to support /win32icon in mcs
677 internal void DefineIconResource (string iconFileName)
679 if (iconFileName == null)
680 throw new ArgumentNullException ("iconFileName");
681 if (iconFileName.Length == 0)
682 throw new ArgumentException ("iconFileName");
683 if (!File.Exists (iconFileName) || Directory.Exists (iconFileName))
684 throw new FileNotFoundException ("File '" + iconFileName + "' does not exists or is a directory.");
686 using (FileStream fs = new FileStream (iconFileName, FileMode.Open, FileAccess.Read)) {
687 Win32IconFileReader reader = new Win32IconFileReader (fs);
689 ICONDIRENTRY[] entries = reader.ReadIcons ();
691 Win32IconResource[] icons = new Win32IconResource [entries.Length];
692 for (int i = 0; i < entries.Length; ++i) {
693 icons [i] = new Win32IconResource (i + 1, 0, entries [i]);
694 AddUnmanagedResource (icons [i]);
697 Win32GroupIconResource group = new Win32GroupIconResource (1, 0, icons);
698 AddUnmanagedResource (group);
702 private void DefineVersionInfoResourceImpl (string fileName)
704 if (versioninfo_culture != null)
705 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
706 version_res.Version = version == null ? "0.0.0.0" : version;
708 if (cattrs != null) {
709 switch (native_resource) {
710 case NativeResourceType.Assembly:
711 foreach (CustomAttributeBuilder cb in cattrs) {
712 string attrname = cb.Ctor.ReflectedType.FullName;
714 if (attrname == "System.Reflection.AssemblyProductAttribute")
715 version_res.ProductName = cb.string_arg ();
716 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
717 version_res.CompanyName = cb.string_arg ();
718 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
719 version_res.LegalCopyright = cb.string_arg ();
720 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
721 version_res.LegalTrademarks = cb.string_arg ();
722 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
723 if (!IsCompilerContext)
724 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
725 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
726 string fileversion = cb.string_arg ();
727 if (!IsCompilerContext || fileversion != null && fileversion.Length != 0)
728 version_res.FileVersion = fileversion;
729 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
730 version_res.ProductVersion = cb.string_arg ();
731 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
732 version_res.FileDescription = cb.string_arg ();
733 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
734 version_res.Comments = cb.string_arg ();
737 case NativeResourceType.Explicit:
738 foreach (CustomAttributeBuilder cb in cattrs) {
739 string attrname = cb.Ctor.ReflectedType.FullName;
741 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
742 if (!IsCompilerContext)
743 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
744 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
745 version_res.Comments = cb.string_arg ();
751 version_res.OriginalFilename = fileName;
753 if (IsCompilerContext) {
754 version_res.InternalName = fileName;
755 if (version_res.ProductVersion.Trim ().Length == 0)
756 version_res.ProductVersion = version_res.FileVersion;
758 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
761 AddUnmanagedResource (version_res);
764 public ModuleBuilder GetDynamicModule (string name)
767 throw new ArgumentNullException ("name");
768 if (name.Length == 0)
769 throw new ArgumentException ("Empty name is not legal.", "name");
772 for (int i = 0; i < modules.Length; ++i)
773 if (modules [i].name == name)
778 public override Type[] GetExportedTypes ()
780 throw not_supported ();
783 public override FileStream GetFile (string name)
785 throw not_supported ();
788 public override FileStream[] GetFiles(bool getResourceModules) {
789 throw not_supported ();
792 internal override Module[] GetModulesInternal () {
794 return new Module [0];
796 return (Module[])modules.Clone ();
799 internal override Type[] GetTypes (bool exportedOnly) {
801 if (modules != null) {
802 for (int i = 0; i < modules.Length; ++i) {
803 Type[] types = modules [i].GetTypes ();
807 Type[] tmp = new Type [res.Length + types.Length];
808 Array.Copy (res, 0, tmp, 0, res.Length);
809 Array.Copy (types, 0, tmp, res.Length, types.Length);
813 if (loaded_modules != null) {
814 for (int i = 0; i < loaded_modules.Length; ++i) {
815 Type[] types = loaded_modules [i].GetTypes ();
819 Type[] tmp = new Type [res.Length + types.Length];
820 Array.Copy (res, 0, tmp, 0, res.Length);
821 Array.Copy (types, 0, tmp, res.Length, types.Length);
826 return res == null ? Type.EmptyTypes : res;
829 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
830 throw not_supported ();
833 public override string[] GetManifestResourceNames() {
834 throw not_supported ();
837 public override Stream GetManifestResourceStream(string name) {
838 throw not_supported ();
840 public override Stream GetManifestResourceStream(Type type, string name) {
841 throw not_supported ();
845 * This is set when the the AssemblyBuilder is created by (g)mcs
848 internal bool IsCompilerContext
850 get { return is_compiler_context; }
853 internal bool IsSave {
855 return access != (uint)AssemblyBuilderAccess.Run;
859 internal bool IsRun {
861 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
863 || access == (uint)AssemblyBuilderAccess.RunAndCollect
870 internal string AssemblyDir {
877 * Mono extension. If this is set, the assembly can only contain one
878 * module, access should be Save, and the saved image will not contain an
881 internal bool IsModuleOnly {
883 return is_module_only;
886 is_module_only = value;
890 ModuleBuilder manifest_module;
893 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
894 // on an assemblybuilder.
896 internal override Module GetManifestModule () {
897 if (manifest_module == null)
898 manifest_module = DefineDynamicModule ("Default Dynamic Module");
899 return manifest_module;
902 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
904 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
906 this.peKind = portableExecutableKind;
907 this.machine = imageFileMachine;
909 if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
910 throw new NotImplementedException (peKind.ToString ());
911 if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
912 throw new NotImplementedException (machine.ToString ());
914 if (resource_writers != null) {
915 foreach (IResourceWriter writer in resource_writers) {
921 // Create a main module if not already created
922 ModuleBuilder mainModule = null;
923 if (modules != null) {
924 foreach (ModuleBuilder module in modules)
925 if (module.FullyQualifiedName == assemblyFileName)
928 if (mainModule == null)
929 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
932 mainModule.IsMain = true;
935 * Create a new entry point if the one specified
936 * by the user is in another module.
938 if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
940 if (entry_point.GetParameters ().Length == 1)
941 paramTypes = new Type [] { typeof (string) };
943 paramTypes = Type.EmptyTypes;
945 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
946 ILGenerator ilgen = mb.GetILGenerator ();
947 if (paramTypes.Length == 1)
948 ilgen.Emit (OpCodes.Ldarg_0);
949 ilgen.Emit (OpCodes.Tailcall);
950 ilgen.Emit (OpCodes.Call, entry_point);
951 ilgen.Emit (OpCodes.Ret);
956 if (version_res != null)
957 DefineVersionInfoResourceImpl (assemblyFileName);
960 // runtime needs to value to embed it into the assembly
961 public_key = sn.PublicKey;
964 foreach (ModuleBuilder module in modules)
965 if (module != mainModule)
968 // Write out the main module at the end, because it needs to
969 // contain the hash of the other modules
972 if ((sn != null) && (sn.CanSign)) {
973 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
979 public void Save (string assemblyFileName)
981 Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
984 public void SetEntryPoint (MethodInfo entryMethod)
986 SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
989 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
991 if (entryMethod == null)
992 throw new ArgumentNullException ("entryMethod");
993 if (entryMethod.DeclaringType.Assembly != this)
994 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
996 entry_point = entryMethod;
1000 public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
1002 if (customBuilder == null)
1003 throw new ArgumentNullException ("customBuilder");
1005 if (IsCompilerContext) {
1006 string attrname = customBuilder.Ctor.ReflectedType.FullName;
1010 if (attrname == "System.Reflection.AssemblyVersionAttribute") {
1011 version = create_assembly_version (customBuilder.string_arg ());
1013 } else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
1014 culture = GetCultureString (customBuilder.string_arg ());
1015 } else if (attrname == "System.Reflection.AssemblyAlgorithmIdAttribute") {
1016 data = customBuilder.Data;
1018 algid = (uint) data [pos];
1019 algid |= ((uint) data [pos + 1]) << 8;
1020 algid |= ((uint) data [pos + 2]) << 16;
1021 algid |= ((uint) data [pos + 3]) << 24;
1022 } else if (attrname == "System.Reflection.AssemblyFlagsAttribute") {
1023 data = customBuilder.Data;
1025 flags |= (uint) data [pos];
1026 flags |= ((uint) data [pos + 1]) << 8;
1027 flags |= ((uint) data [pos + 2]) << 16;
1028 flags |= ((uint) data [pos + 3]) << 24;
1030 // ignore PublicKey flag if assembly is not strongnamed
1032 flags &= ~(uint) AssemblyNameFlags.PublicKey;
1036 if (cattrs != null) {
1037 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
1038 cattrs.CopyTo (new_array, 0);
1039 new_array [cattrs.Length] = customBuilder;
1042 cattrs = new CustomAttributeBuilder [1];
1043 cattrs [0] = customBuilder;
1048 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
1050 throw new ArgumentNullException ("con");
1051 if (binaryAttribute == null)
1052 throw new ArgumentNullException ("binaryAttribute");
1054 SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
1057 internal void SetCorlibTypeBuilders (Type corlib_object_type, Type corlib_value_type, Type corlib_enum_type) {
1058 this.corlib_object_type = corlib_object_type;
1059 this.corlib_value_type = corlib_value_type;
1060 this.corlib_enum_type = corlib_enum_type;
1063 internal void SetCorlibTypeBuilders (Type corlib_object_type, Type corlib_value_type, Type corlib_enum_type, Type corlib_void_type)
1065 SetCorlibTypeBuilders (corlib_object_type, corlib_value_type, corlib_enum_type);
1066 this.corlib_void_type = corlib_void_type;
1069 private Exception not_supported () {
1070 // Strange message but this is what MS.NET prints...
1071 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
1074 private void check_name_and_filename (string name, string fileName,
1075 bool fileNeedsToExists) {
1077 throw new ArgumentNullException ("name");
1078 if (fileName == null)
1079 throw new ArgumentNullException ("fileName");
1080 if (name.Length == 0)
1081 throw new ArgumentException ("Empty name is not legal.", "name");
1082 if (fileName.Length == 0)
1083 throw new ArgumentException ("Empty file name is not legal.", "fileName");
1084 if (Path.GetFileName (fileName) != fileName)
1085 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
1087 // Resource files are created/searched under the assembly storage
1089 string fullFileName = fileName;
1091 fullFileName = Path.Combine (dir, fileName);
1093 if (fileNeedsToExists && !File.Exists (fullFileName))
1094 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
1096 if (resources != null) {
1097 for (int i = 0; i < resources.Length; ++i) {
1098 if (resources [i].filename == fullFileName)
1099 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
1100 if (resources [i].name == name)
1101 throw new ArgumentException ("Duplicate name '" + name + "'");
1105 if (modules != null) {
1106 for (int i = 0; i < modules.Length; ++i) {
1107 // Use fileName instead of fullFileName here
1108 if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
1109 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
1110 if (modules [i].Name == name)
1111 throw new ArgumentException ("Duplicate name '" + name + "'");
1116 private String create_assembly_version (String version) {
1117 String[] parts = version.Split ('.');
1118 int[] ver = new int [4] { 0, 0, 0, 0 };
1120 if ((parts.Length < 0) || (parts.Length > 4))
1121 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1123 for (int i = 0; i < parts.Length; ++i) {
1124 if (parts [i] == "*") {
1125 DateTime now = DateTime.Now;
1128 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1129 if (parts.Length == 3)
1130 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1134 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1136 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1140 ver [i] = Int32.Parse (parts [i]);
1142 catch (FormatException) {
1143 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1148 return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1151 private string GetCultureString (string str)
1153 return (str == "neutral" ? String.Empty : str);
1156 internal override AssemblyName UnprotectedGetName ()
1158 AssemblyName an = base.UnprotectedGetName ();
1160 an.SetPublicKey (sn.PublicKey);
1161 an.SetPublicKeyToken (sn.PublicKeyToken);
1166 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1167 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1169 if (!IsCompilerContext)
1170 return new MonoGenericClass (gtd, typeArguments);
1172 GenericInstanceKey key = new GenericInstanceKey (gtd, typeArguments);
1173 MonoGenericClass res = (MonoGenericClass)generic_instances [key];
1175 res = new MonoGenericClass (gtd, typeArguments);
1176 generic_instances [key] = res;
1181 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1183 throw new NotImplementedException ();
1186 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1188 throw new NotImplementedException ();
1191 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1193 throw new NotImplementedException ();
1196 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1198 throw new NotImplementedException ();
1202 public override Type GetType (string name, bool throwOnError, bool ignoreCase)
1205 throw new ArgumentNullException (name);
1206 if (name.Length == 0)
1207 throw new ArgumentException ("name", "Name cannot be empty");
1209 var res = InternalGetType (null, name, throwOnError, ignoreCase);
1210 if (res is TypeBuilder) {
1212 throw new TypeLoadException (string.Format ("Could not load type '{0}' from assembly '{1}'", name, this.name));
1218 public override Module GetModule (String name)
1221 throw new ArgumentNullException ("name");
1222 if (name.Length == 0)
1223 throw new ArgumentException ("Name can't be empty");
1225 if (modules == null)
1228 foreach (Module module in modules) {
1229 if (module.ScopeName == name)
1236 public override Module[] GetModules (bool getResourceModules)
1238 Module[] modules = GetModulesInternal ();
1240 if (!getResourceModules) {
1241 ArrayList result = new ArrayList (modules.Length);
1242 foreach (Module m in modules)
1243 if (!m.IsResource ())
1245 return (Module[])result.ToArray (typeof (Module));
1250 [MonoTODO ("This always returns an empty array")]
1251 public override AssemblyName[] GetReferencedAssemblies () {
1252 return GetReferencedAssemblies (this);
1255 public override Module[] GetLoadedModules (bool getResourceModules)
1257 return GetModules (getResourceModules);
1260 //FIXME MS has issues loading satelite assemblies from SRE
1261 public override Assembly GetSatelliteAssembly (CultureInfo culture)
1263 return GetSatelliteAssembly (culture, null, true);
1266 //FIXME MS has issues loading satelite assemblies from SRE
1267 public override Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
1269 return GetSatelliteAssembly (culture, version, true);
1272 public override Module ManifestModule {
1274 return GetManifestModule ();
1278 public override bool GlobalAssemblyCache {
1284 public override bool IsDynamic {
1285 get { return true; }