AssemblyBuilder.cs 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. //
  2. // System.Reflection.Emit/AssemblyBuilder.cs
  3. //
  4. // Author:
  5. // Paolo Molaro ([email protected])
  6. //
  7. // (C) 2001 Ximian, Inc. http://www.ximian.com
  8. //
  9. //
  10. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. using System;
  32. using System.Reflection;
  33. using System.Resources;
  34. using System.IO;
  35. using System.Security.Policy;
  36. using System.Runtime.Serialization;
  37. using System.Globalization;
  38. using System.Runtime.CompilerServices;
  39. using System.Collections;
  40. using System.Runtime.InteropServices;
  41. using System.Security;
  42. using System.Security.Cryptography;
  43. using System.Security.Permissions;
  44. using Mono.Security;
  45. using Mono.Security.Cryptography;
  46. namespace System.Reflection.Emit
  47. {
  48. internal enum NativeResourceType
  49. {
  50. None,
  51. Unmanaged,
  52. Assembly,
  53. Explicit
  54. }
  55. internal struct RefEmitPermissionSet {
  56. public SecurityAction action;
  57. public string pset;
  58. public RefEmitPermissionSet (SecurityAction action, string pset) {
  59. this.action = action;
  60. this.pset = pset;
  61. }
  62. }
  63. internal struct MonoResource {
  64. public byte[] data;
  65. public string name;
  66. public string filename;
  67. public ResourceAttributes attrs;
  68. public int offset;
  69. public Stream stream;
  70. }
  71. internal struct MonoWin32Resource {
  72. public int res_type;
  73. public int res_id;
  74. public int lang_id;
  75. public byte[] data;
  76. public MonoWin32Resource (int res_type, int res_id, int lang_id, byte[] data) {
  77. this.res_type = res_type;
  78. this.res_id = res_id;
  79. this.lang_id = lang_id;
  80. this.data = data;
  81. }
  82. }
  83. #if NET_2_0
  84. [ComVisible (true)]
  85. [ComDefaultInterface (typeof (_AssemblyBuilder))]
  86. #endif
  87. [ClassInterface (ClassInterfaceType.None)]
  88. public sealed class AssemblyBuilder : Assembly, _AssemblyBuilder {
  89. #pragma warning disable 169, 414
  90. #region Sync with object-internals.h
  91. private UIntPtr dynamic_assembly; /* GC-tracked */
  92. private MethodInfo entry_point;
  93. private ModuleBuilder[] modules;
  94. private string name;
  95. private string dir;
  96. private CustomAttributeBuilder[] cattrs;
  97. private MonoResource[] resources;
  98. byte[] public_key;
  99. string version;
  100. string culture;
  101. uint algid;
  102. uint flags;
  103. PEFileKinds pekind = PEFileKinds.Dll;
  104. bool delay_sign;
  105. uint access;
  106. Module[] loaded_modules;
  107. MonoWin32Resource[] win32_resources;
  108. private RefEmitPermissionSet[] permissions_minimum;
  109. private RefEmitPermissionSet[] permissions_optional;
  110. private RefEmitPermissionSet[] permissions_refused;
  111. PortableExecutableKinds peKind;
  112. ImageFileMachine machine;
  113. bool corlib_internal;
  114. Type[] type_forwarders;
  115. #endregion
  116. #pragma warning restore 169, 414
  117. internal Type corlib_object_type = typeof (System.Object);
  118. internal Type corlib_value_type = typeof (System.ValueType);
  119. internal Type corlib_enum_type = typeof (System.Enum);
  120. internal Type corlib_void_type = typeof (void);
  121. ArrayList resource_writers = null;
  122. Win32VersionResource version_res;
  123. bool created;
  124. bool is_module_only;
  125. private Mono.Security.StrongName sn;
  126. NativeResourceType native_resource;
  127. readonly bool is_compiler_context;
  128. string versioninfo_culture;
  129. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  130. private static extern void basic_init (AssemblyBuilder ab);
  131. /* Keep this in sync with codegen.cs in mcs */
  132. private const AssemblyBuilderAccess COMPILER_ACCESS = (AssemblyBuilderAccess) 0x800;
  133. internal AssemblyBuilder (AssemblyName n, string directory, AssemblyBuilderAccess access, bool corlib_internal)
  134. {
  135. #if BOOTSTRAP_WITH_OLDLIB
  136. is_compiler_context = true;
  137. #else
  138. is_compiler_context = (access & COMPILER_ACCESS) != 0;
  139. #endif
  140. // remove Mono specific flag to allow enum check to pass
  141. access &= ~COMPILER_ACCESS;
  142. #if NET_2_0
  143. if (!Enum.IsDefined (typeof (AssemblyBuilderAccess), access))
  144. throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
  145. "Argument value {0} is not valid.", (int) access),
  146. "access");
  147. #endif
  148. #if NET_4_0
  149. if ((access & AssemblyBuilderAccess.RunAndCollect) == AssemblyBuilderAccess.RunAndCollect)
  150. throw new NotSupportedException ("RunAndCollect not yet supported.");
  151. #endif
  152. name = n.Name;
  153. this.access = (uint)access;
  154. flags = (uint) n.Flags;
  155. // don't call GetCurrentDirectory for Run-only builders (CAS may not like that)
  156. if (IsSave && (directory == null || directory.Length == 0)) {
  157. dir = Directory.GetCurrentDirectory ();
  158. } else {
  159. dir = directory;
  160. }
  161. /* Set defaults from n */
  162. if (n.CultureInfo != null) {
  163. culture = n.CultureInfo.Name;
  164. versioninfo_culture = n.CultureInfo.Name;
  165. }
  166. Version v = n.Version;
  167. if (v != null) {
  168. version = v.ToString ();
  169. }
  170. if (n.KeyPair != null) {
  171. // full keypair is available (for signing)
  172. sn = n.KeyPair.StrongName ();
  173. } else {
  174. // public key is available (for delay-signing)
  175. byte[] pk = n.GetPublicKey ();
  176. if ((pk != null) && (pk.Length > 0)) {
  177. sn = new Mono.Security.StrongName (pk);
  178. }
  179. }
  180. if (sn != null)
  181. flags |= (uint) AssemblyNameFlags.PublicKey;
  182. this.corlib_internal = corlib_internal;
  183. basic_init (this);
  184. }
  185. public override string CodeBase {
  186. get {
  187. throw not_supported ();
  188. }
  189. }
  190. public override MethodInfo EntryPoint {
  191. get {
  192. return entry_point;
  193. }
  194. }
  195. public override string Location {
  196. get {
  197. throw not_supported ();
  198. }
  199. }
  200. #if NET_1_1
  201. /* This is to keep signature compatibility with MS.NET */
  202. public override string ImageRuntimeVersion {
  203. get {
  204. return base.ImageRuntimeVersion;
  205. }
  206. }
  207. #endif
  208. #if NET_2_0
  209. [MonoTODO]
  210. public override bool ReflectionOnly {
  211. get { return base.ReflectionOnly; }
  212. }
  213. #endif
  214. public void AddResourceFile (string name, string fileName)
  215. {
  216. AddResourceFile (name, fileName, ResourceAttributes.Public);
  217. }
  218. public void AddResourceFile (string name, string fileName, ResourceAttributes attribute)
  219. {
  220. AddResourceFile (name, fileName, attribute, true);
  221. }
  222. private void AddResourceFile (string name, string fileName, ResourceAttributes attribute, bool fileNeedsToExists)
  223. {
  224. check_name_and_filename (name, fileName, fileNeedsToExists);
  225. // Resource files are created/searched under the assembly storage
  226. // directory
  227. if (dir != null)
  228. fileName = Path.Combine (dir, fileName);
  229. if (resources != null) {
  230. MonoResource[] new_r = new MonoResource [resources.Length + 1];
  231. System.Array.Copy(resources, new_r, resources.Length);
  232. resources = new_r;
  233. } else {
  234. resources = new MonoResource [1];
  235. }
  236. int p = resources.Length - 1;
  237. resources [p].name = name;
  238. resources [p].filename = fileName;
  239. resources [p].attrs = attribute;
  240. }
  241. /// <summary>
  242. /// Don't change the method name and parameters order. It is used by mcs
  243. /// </summary>
  244. internal void AddPermissionRequests (PermissionSet required, PermissionSet optional, PermissionSet refused)
  245. {
  246. if (created)
  247. throw new InvalidOperationException ("Assembly was already saved.");
  248. // required for base Assembly class (so the permissions
  249. // can be used even if the assembly isn't saved to disk)
  250. _minimum = required;
  251. _optional = optional;
  252. _refuse = refused;
  253. // required to reuse AddDeclarativeSecurity support
  254. // already present in the runtime
  255. if (required != null) {
  256. permissions_minimum = new RefEmitPermissionSet [1];
  257. permissions_minimum [0] = new RefEmitPermissionSet (
  258. SecurityAction.RequestMinimum, required.ToXml ().ToString ());
  259. }
  260. if (optional != null) {
  261. permissions_optional = new RefEmitPermissionSet [1];
  262. permissions_optional [0] = new RefEmitPermissionSet (
  263. SecurityAction.RequestOptional, optional.ToXml ().ToString ());
  264. }
  265. if (refused != null) {
  266. permissions_refused = new RefEmitPermissionSet [1];
  267. permissions_refused [0] = new RefEmitPermissionSet (
  268. SecurityAction.RequestRefuse, refused.ToXml ().ToString ());
  269. }
  270. }
  271. internal void EmbedResourceFile (string name, string fileName)
  272. {
  273. EmbedResourceFile (name, fileName, ResourceAttributes.Public);
  274. }
  275. internal void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute)
  276. {
  277. if (resources != null) {
  278. MonoResource[] new_r = new MonoResource [resources.Length + 1];
  279. System.Array.Copy(resources, new_r, resources.Length);
  280. resources = new_r;
  281. } else {
  282. resources = new MonoResource [1];
  283. }
  284. int p = resources.Length - 1;
  285. resources [p].name = name;
  286. resources [p].attrs = attribute;
  287. try {
  288. FileStream s = new FileStream (fileName, FileMode.Open, FileAccess.Read);
  289. long len = s.Length;
  290. resources [p].data = new byte [len];
  291. s.Read (resources [p].data, 0, (int)len);
  292. s.Close ();
  293. } catch {
  294. /* do something */
  295. }
  296. }
  297. internal void EmbedResource (string name, byte[] blob, ResourceAttributes attribute)
  298. {
  299. if (resources != null) {
  300. MonoResource[] new_r = new MonoResource [resources.Length + 1];
  301. System.Array.Copy(resources, new_r, resources.Length);
  302. resources = new_r;
  303. } else {
  304. resources = new MonoResource [1];
  305. }
  306. int p = resources.Length - 1;
  307. resources [p].name = name;
  308. resources [p].attrs = attribute;
  309. resources [p].data = blob;
  310. }
  311. #if NET_2_0
  312. internal void AddTypeForwarder (Type t) {
  313. if (t == null)
  314. throw new ArgumentNullException ("t");
  315. if (type_forwarders == null) {
  316. type_forwarders = new Type [1] { t };
  317. } else {
  318. Type[] arr = new Type [type_forwarders.Length + 1];
  319. Array.Copy (type_forwarders, arr, type_forwarders.Length);
  320. arr [type_forwarders.Length] = t;
  321. type_forwarders = arr;
  322. }
  323. }
  324. #endif
  325. public ModuleBuilder DefineDynamicModule (string name)
  326. {
  327. return DefineDynamicModule (name, name, false, true);
  328. }
  329. public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
  330. {
  331. return DefineDynamicModule (name, name, emitSymbolInfo, true);
  332. }
  333. public ModuleBuilder DefineDynamicModule(string name, string fileName)
  334. {
  335. return DefineDynamicModule (name, fileName, false, false);
  336. }
  337. public ModuleBuilder DefineDynamicModule (string name, string fileName,
  338. bool emitSymbolInfo)
  339. {
  340. return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
  341. }
  342. private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
  343. {
  344. check_name_and_filename (name, fileName, false);
  345. if (!transient) {
  346. if (Path.GetExtension (fileName) == String.Empty)
  347. throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
  348. if (!IsSave)
  349. throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
  350. if (created)
  351. throw new InvalidOperationException ("Assembly was already saved.");
  352. }
  353. ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
  354. if ((modules != null) && is_module_only)
  355. throw new InvalidOperationException ("A module-only assembly can only contain one module.");
  356. if (modules != null) {
  357. ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
  358. System.Array.Copy(modules, new_modules, modules.Length);
  359. modules = new_modules;
  360. } else {
  361. modules = new ModuleBuilder [1];
  362. }
  363. modules [modules.Length - 1] = r;
  364. return r;
  365. }
  366. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  367. private extern Module InternalAddModule (string fileName);
  368. /*
  369. * Mono extension to support /addmodule in mcs.
  370. */
  371. internal Module AddModule (string fileName)
  372. {
  373. if (fileName == null)
  374. throw new ArgumentNullException (fileName);
  375. Module m = InternalAddModule (fileName);
  376. if (loaded_modules != null) {
  377. Module[] new_modules = new Module [loaded_modules.Length + 1];
  378. System.Array.Copy (loaded_modules, new_modules, loaded_modules.Length);
  379. loaded_modules = new_modules;
  380. } else {
  381. loaded_modules = new Module [1];
  382. }
  383. loaded_modules [loaded_modules.Length - 1] = m;
  384. return m;
  385. }
  386. public IResourceWriter DefineResource (string name, string description, string fileName)
  387. {
  388. return DefineResource (name, description, fileName, ResourceAttributes.Public);
  389. }
  390. public IResourceWriter DefineResource (string name, string description,
  391. string fileName, ResourceAttributes attribute)
  392. {
  393. IResourceWriter writer;
  394. // description seems to be ignored
  395. AddResourceFile (name, fileName, attribute, false);
  396. writer = new ResourceWriter (fileName);
  397. if (resource_writers == null)
  398. resource_writers = new ArrayList ();
  399. resource_writers.Add (writer);
  400. return writer;
  401. }
  402. private void AddUnmanagedResource (Win32Resource res) {
  403. MemoryStream ms = new MemoryStream ();
  404. res.WriteTo (ms);
  405. if (win32_resources != null) {
  406. MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
  407. System.Array.Copy (win32_resources, new_res, win32_resources.Length);
  408. win32_resources = new_res;
  409. }
  410. else
  411. win32_resources = new MonoWin32Resource [1];
  412. win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
  413. }
  414. [MonoTODO ("Not currently implemenented")]
  415. public void DefineUnmanagedResource (byte[] resource)
  416. {
  417. if (resource == null)
  418. throw new ArgumentNullException ("resource");
  419. if (native_resource != NativeResourceType.None)
  420. throw new ArgumentException ("Native resource has already been defined.");
  421. // avoid definition of more than one unmanaged resource
  422. native_resource = NativeResourceType.Unmanaged;
  423. /*
  424. * The format of the argument byte array is not documented
  425. * so this method is impossible to implement.
  426. */
  427. throw new NotImplementedException ();
  428. }
  429. public void DefineUnmanagedResource (string resourceFileName)
  430. {
  431. if (resourceFileName == null)
  432. throw new ArgumentNullException ("resourceFileName");
  433. if (resourceFileName.Length == 0)
  434. throw new ArgumentException ("resourceFileName");
  435. if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
  436. throw new FileNotFoundException ("File '" + resourceFileName + "' does not exists or is a directory.");
  437. if (native_resource != NativeResourceType.None)
  438. throw new ArgumentException ("Native resource has already been defined.");
  439. // avoid definition of more than one unmanaged resource
  440. native_resource = NativeResourceType.Unmanaged;
  441. using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
  442. Win32ResFileReader reader = new Win32ResFileReader (fs);
  443. foreach (Win32EncodedResource res in reader.ReadResources ()) {
  444. if (res.Name.IsName || res.Type.IsName)
  445. throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
  446. AddUnmanagedResource (res);
  447. }
  448. }
  449. }
  450. public void DefineVersionInfoResource ()
  451. {
  452. if (native_resource != NativeResourceType.None)
  453. throw new ArgumentException ("Native resource has already been defined.");
  454. // avoid definition of more than one unmanaged resource
  455. native_resource = NativeResourceType.Assembly;
  456. version_res = new Win32VersionResource (1, 0, IsCompilerContext);
  457. }
  458. public void DefineVersionInfoResource (string product, string productVersion,
  459. string company, string copyright, string trademark)
  460. {
  461. if (native_resource != NativeResourceType.None)
  462. throw new ArgumentException ("Native resource has already been defined.");
  463. // avoid definition of more than one unmanaged resource
  464. native_resource = NativeResourceType.Explicit;
  465. /*
  466. * We can only create the resource later, when the file name and
  467. * the binary version is known.
  468. */
  469. version_res = new Win32VersionResource (1, 0, false);
  470. version_res.ProductName = product != null ? product : " ";
  471. version_res.ProductVersion = productVersion != null ? productVersion : " ";
  472. version_res.CompanyName = company != null ? company : " ";
  473. version_res.LegalCopyright = copyright != null ? copyright : " ";
  474. version_res.LegalTrademarks = trademark != null ? trademark : " ";
  475. }
  476. /*
  477. * Mono extension to support /win32icon in mcs
  478. */
  479. internal void DefineIconResource (string iconFileName)
  480. {
  481. if (iconFileName == null)
  482. throw new ArgumentNullException ("iconFileName");
  483. if (iconFileName.Length == 0)
  484. throw new ArgumentException ("iconFileName");
  485. if (!File.Exists (iconFileName) || Directory.Exists (iconFileName))
  486. throw new FileNotFoundException ("File '" + iconFileName + "' does not exists or is a directory.");
  487. using (FileStream fs = new FileStream (iconFileName, FileMode.Open, FileAccess.Read)) {
  488. Win32IconFileReader reader = new Win32IconFileReader (fs);
  489. ICONDIRENTRY[] entries = reader.ReadIcons ();
  490. Win32IconResource[] icons = new Win32IconResource [entries.Length];
  491. for (int i = 0; i < entries.Length; ++i) {
  492. icons [i] = new Win32IconResource (i + 1, 0, entries [i]);
  493. AddUnmanagedResource (icons [i]);
  494. }
  495. Win32GroupIconResource group = new Win32GroupIconResource (1, 0, icons);
  496. AddUnmanagedResource (group);
  497. }
  498. }
  499. private void DefineVersionInfoResourceImpl (string fileName)
  500. {
  501. if (versioninfo_culture != null)
  502. version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
  503. version_res.Version = version == null ? "0.0.0.0" : version;
  504. if (cattrs != null) {
  505. switch (native_resource) {
  506. case NativeResourceType.Assembly:
  507. foreach (CustomAttributeBuilder cb in cattrs) {
  508. string attrname = cb.Ctor.ReflectedType.FullName;
  509. if (attrname == "System.Reflection.AssemblyProductAttribute")
  510. version_res.ProductName = cb.string_arg ();
  511. else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
  512. version_res.CompanyName = cb.string_arg ();
  513. else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
  514. version_res.LegalCopyright = cb.string_arg ();
  515. else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
  516. version_res.LegalTrademarks = cb.string_arg ();
  517. else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
  518. if (!IsCompilerContext)
  519. version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
  520. } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
  521. string fileversion = cb.string_arg ();
  522. if (!IsCompilerContext || fileversion != null && fileversion.Length != 0)
  523. version_res.FileVersion = fileversion;
  524. } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
  525. version_res.ProductVersion = cb.string_arg ();
  526. else if (attrname == "System.Reflection.AssemblyTitleAttribute")
  527. version_res.FileDescription = cb.string_arg ();
  528. else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
  529. version_res.Comments = cb.string_arg ();
  530. }
  531. break;
  532. case NativeResourceType.Explicit:
  533. foreach (CustomAttributeBuilder cb in cattrs) {
  534. string attrname = cb.Ctor.ReflectedType.FullName;
  535. if (attrname == "System.Reflection.AssemblyCultureAttribute") {
  536. if (!IsCompilerContext)
  537. version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
  538. } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
  539. version_res.Comments = cb.string_arg ();
  540. }
  541. break;
  542. }
  543. }
  544. version_res.OriginalFilename = fileName;
  545. if (IsCompilerContext) {
  546. version_res.InternalName = fileName;
  547. if (version_res.ProductVersion.Trim ().Length == 0)
  548. version_res.ProductVersion = version_res.FileVersion;
  549. } else {
  550. version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
  551. }
  552. AddUnmanagedResource (version_res);
  553. }
  554. public ModuleBuilder GetDynamicModule (string name)
  555. {
  556. if (name == null)
  557. throw new ArgumentNullException ("name");
  558. if (name.Length == 0)
  559. throw new ArgumentException ("Empty name is not legal.", "name");
  560. if (modules != null)
  561. for (int i = 0; i < modules.Length; ++i)
  562. if (modules [i].name == name)
  563. return modules [i];
  564. return null;
  565. }
  566. public override Type[] GetExportedTypes ()
  567. {
  568. throw not_supported ();
  569. }
  570. public override FileStream GetFile (string name)
  571. {
  572. throw not_supported ();
  573. }
  574. public override FileStream[] GetFiles(bool getResourceModules) {
  575. throw not_supported ();
  576. }
  577. internal override Module[] GetModulesInternal () {
  578. if (modules == null)
  579. return new Module [0];
  580. else
  581. return (Module[])modules.Clone ();
  582. }
  583. internal override Type[] GetTypes (bool exportedOnly) {
  584. Type[] res = null;
  585. if (modules != null) {
  586. for (int i = 0; i < modules.Length; ++i) {
  587. Type[] types = modules [i].GetTypes ();
  588. if (res == null)
  589. res = types;
  590. else {
  591. Type[] tmp = new Type [res.Length + types.Length];
  592. Array.Copy (res, 0, tmp, 0, res.Length);
  593. Array.Copy (types, 0, tmp, res.Length, types.Length);
  594. }
  595. }
  596. }
  597. if (loaded_modules != null) {
  598. for (int i = 0; i < loaded_modules.Length; ++i) {
  599. Type[] types = loaded_modules [i].GetTypes ();
  600. if (res == null)
  601. res = types;
  602. else {
  603. Type[] tmp = new Type [res.Length + types.Length];
  604. Array.Copy (res, 0, tmp, 0, res.Length);
  605. Array.Copy (types, 0, tmp, res.Length, types.Length);
  606. }
  607. }
  608. }
  609. return res == null ? Type.EmptyTypes : res;
  610. }
  611. public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
  612. throw not_supported ();
  613. }
  614. public override string[] GetManifestResourceNames() {
  615. throw not_supported ();
  616. }
  617. public override Stream GetManifestResourceStream(string name) {
  618. throw not_supported ();
  619. }
  620. public override Stream GetManifestResourceStream(Type type, string name) {
  621. throw not_supported ();
  622. }
  623. /*
  624. * This is set when the the AssemblyBuilder is created by (g)mcs
  625. * or vbnc.
  626. */
  627. internal bool IsCompilerContext
  628. {
  629. get { return is_compiler_context; }
  630. }
  631. internal bool IsSave {
  632. get {
  633. return access != (uint)AssemblyBuilderAccess.Run;
  634. }
  635. }
  636. internal string AssemblyDir {
  637. get {
  638. return dir;
  639. }
  640. }
  641. /*
  642. * Mono extension. If this is set, the assembly can only contain one
  643. * module, access should be Save, and the saved image will not contain an
  644. * assembly manifest.
  645. */
  646. internal bool IsModuleOnly {
  647. get {
  648. return is_module_only;
  649. }
  650. set {
  651. is_module_only = value;
  652. }
  653. }
  654. #if NET_2_0 || BOOTSTRAP_NET_2_0
  655. ModuleBuilder manifest_module;
  656. //
  657. // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
  658. // on an assemblybuilder.
  659. //
  660. internal override Module GetManifestModule () {
  661. if (manifest_module == null)
  662. manifest_module = DefineDynamicModule ("Default Dynamic Module");
  663. return manifest_module;
  664. }
  665. #endif
  666. #if NET_2_0
  667. public
  668. #else
  669. internal
  670. #endif
  671. void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
  672. {
  673. this.peKind = portableExecutableKind;
  674. this.machine = imageFileMachine;
  675. if (resource_writers != null) {
  676. foreach (IResourceWriter writer in resource_writers) {
  677. writer.Generate ();
  678. writer.Close ();
  679. }
  680. }
  681. // Create a main module if not already created
  682. ModuleBuilder mainModule = null;
  683. if (modules != null) {
  684. foreach (ModuleBuilder module in modules)
  685. if (module.FullyQualifiedName == assemblyFileName)
  686. mainModule = module;
  687. }
  688. if (mainModule == null)
  689. mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
  690. if (!is_module_only)
  691. mainModule.IsMain = true;
  692. /*
  693. * Create a new entry point if the one specified
  694. * by the user is in another module.
  695. */
  696. if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
  697. Type[] paramTypes;
  698. if (entry_point.GetParameters ().Length == 1)
  699. paramTypes = new Type [] { typeof (string) };
  700. else
  701. paramTypes = Type.EmptyTypes;
  702. MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
  703. ILGenerator ilgen = mb.GetILGenerator ();
  704. if (paramTypes.Length == 1)
  705. ilgen.Emit (OpCodes.Ldarg_0);
  706. ilgen.Emit (OpCodes.Tailcall);
  707. ilgen.Emit (OpCodes.Call, entry_point);
  708. ilgen.Emit (OpCodes.Ret);
  709. entry_point = mb;
  710. }
  711. if (version_res != null)
  712. DefineVersionInfoResourceImpl (assemblyFileName);
  713. if (sn != null) {
  714. // runtime needs to value to embed it into the assembly
  715. public_key = sn.PublicKey;
  716. }
  717. foreach (ModuleBuilder module in modules)
  718. if (module != mainModule)
  719. module.Save ();
  720. // Write out the main module at the end, because it needs to
  721. // contain the hash of the other modules
  722. mainModule.Save ();
  723. if ((sn != null) && (sn.CanSign)) {
  724. sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
  725. }
  726. created = true;
  727. }
  728. public void Save (string assemblyFileName)
  729. {
  730. Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
  731. }
  732. public void SetEntryPoint (MethodInfo entryMethod)
  733. {
  734. SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
  735. }
  736. public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
  737. {
  738. if (entryMethod == null)
  739. throw new ArgumentNullException ("entryMethod");
  740. if (entryMethod.DeclaringType.Assembly != this)
  741. throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
  742. entry_point = entryMethod;
  743. pekind = fileKind;
  744. }
  745. public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
  746. {
  747. if (customBuilder == null)
  748. throw new ArgumentNullException ("customBuilder");
  749. if (IsCompilerContext) {
  750. string attrname = customBuilder.Ctor.ReflectedType.FullName;
  751. byte [] data;
  752. int pos;
  753. if (attrname == "System.Reflection.AssemblyVersionAttribute") {
  754. version = create_assembly_version (customBuilder.string_arg ());
  755. return;
  756. } else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
  757. culture = GetCultureString (customBuilder.string_arg ());
  758. } else if (attrname == "System.Reflection.AssemblyAlgorithmIdAttribute") {
  759. data = customBuilder.Data;
  760. pos = 2;
  761. algid = (uint) data [pos];
  762. algid |= ((uint) data [pos + 1]) << 8;
  763. algid |= ((uint) data [pos + 2]) << 16;
  764. algid |= ((uint) data [pos + 3]) << 24;
  765. } else if (attrname == "System.Reflection.AssemblyFlagsAttribute") {
  766. data = customBuilder.Data;
  767. pos = 2;
  768. flags |= (uint) data [pos];
  769. flags |= ((uint) data [pos + 1]) << 8;
  770. flags |= ((uint) data [pos + 2]) << 16;
  771. flags |= ((uint) data [pos + 3]) << 24;
  772. #if NET_2_0
  773. // ignore PublicKey flag if assembly is not strongnamed
  774. if (sn == null)
  775. flags &= ~(uint) AssemblyNameFlags.PublicKey;
  776. #endif
  777. }
  778. }
  779. if (cattrs != null) {
  780. CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
  781. cattrs.CopyTo (new_array, 0);
  782. new_array [cattrs.Length] = customBuilder;
  783. cattrs = new_array;
  784. } else {
  785. cattrs = new CustomAttributeBuilder [1];
  786. cattrs [0] = customBuilder;
  787. }
  788. }
  789. #if NET_2_0
  790. [ComVisible (true)]
  791. #endif
  792. public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
  793. if (con == null)
  794. throw new ArgumentNullException ("con");
  795. if (binaryAttribute == null)
  796. throw new ArgumentNullException ("binaryAttribute");
  797. SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
  798. }
  799. internal void SetCorlibTypeBuilders (Type corlib_object_type, Type corlib_value_type, Type corlib_enum_type) {
  800. this.corlib_object_type = corlib_object_type;
  801. this.corlib_value_type = corlib_value_type;
  802. this.corlib_enum_type = corlib_enum_type;
  803. }
  804. internal void SetCorlibTypeBuilders (Type corlib_object_type, Type corlib_value_type, Type corlib_enum_type, Type corlib_void_type)
  805. {
  806. SetCorlibTypeBuilders (corlib_object_type, corlib_value_type, corlib_enum_type);
  807. this.corlib_void_type = corlib_void_type;
  808. }
  809. private Exception not_supported () {
  810. // Strange message but this is what MS.NET prints...
  811. return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
  812. }
  813. private void check_name_and_filename (string name, string fileName,
  814. bool fileNeedsToExists) {
  815. if (name == null)
  816. throw new ArgumentNullException ("name");
  817. if (fileName == null)
  818. throw new ArgumentNullException ("fileName");
  819. if (name.Length == 0)
  820. throw new ArgumentException ("Empty name is not legal.", "name");
  821. if (fileName.Length == 0)
  822. throw new ArgumentException ("Empty file name is not legal.", "fileName");
  823. if (Path.GetFileName (fileName) != fileName)
  824. throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
  825. // Resource files are created/searched under the assembly storage
  826. // directory
  827. string fullFileName = fileName;
  828. if (dir != null)
  829. fullFileName = Path.Combine (dir, fileName);
  830. if (fileNeedsToExists && !File.Exists (fullFileName))
  831. throw new FileNotFoundException ("Could not find file '" + fileName + "'");
  832. if (resources != null) {
  833. for (int i = 0; i < resources.Length; ++i) {
  834. if (resources [i].filename == fullFileName)
  835. throw new ArgumentException ("Duplicate file name '" + fileName + "'");
  836. if (resources [i].name == name)
  837. throw new ArgumentException ("Duplicate name '" + name + "'");
  838. }
  839. }
  840. if (modules != null) {
  841. for (int i = 0; i < modules.Length; ++i) {
  842. // Use fileName instead of fullFileName here
  843. if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
  844. throw new ArgumentException ("Duplicate file name '" + fileName + "'");
  845. if (modules [i].Name == name)
  846. throw new ArgumentException ("Duplicate name '" + name + "'");
  847. }
  848. }
  849. }
  850. private String create_assembly_version (String version) {
  851. String[] parts = version.Split ('.');
  852. int[] ver = new int [4] { 0, 0, 0, 0 };
  853. if ((parts.Length < 0) || (parts.Length > 4))
  854. throw new ArgumentException ("The version specified '" + version + "' is invalid");
  855. for (int i = 0; i < parts.Length; ++i) {
  856. if (parts [i] == "*") {
  857. DateTime now = DateTime.Now;
  858. if (i == 2) {
  859. ver [2] = (now - new DateTime (2000, 1, 1)).Days;
  860. if (parts.Length == 3)
  861. ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
  862. }
  863. else
  864. if (i == 3)
  865. ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
  866. else
  867. throw new ArgumentException ("The version specified '" + version + "' is invalid");
  868. }
  869. else {
  870. try {
  871. ver [i] = Int32.Parse (parts [i]);
  872. }
  873. catch (FormatException) {
  874. throw new ArgumentException ("The version specified '" + version + "' is invalid");
  875. }
  876. }
  877. }
  878. return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
  879. }
  880. private string GetCultureString (string str)
  881. {
  882. return (str == "neutral" ? String.Empty : str);
  883. }
  884. internal override AssemblyName UnprotectedGetName ()
  885. {
  886. AssemblyName an = base.UnprotectedGetName ();
  887. if (sn != null) {
  888. an.SetPublicKey (sn.PublicKey);
  889. an.SetPublicKeyToken (sn.PublicKeyToken);
  890. }
  891. return an;
  892. }
  893. void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
  894. {
  895. throw new NotImplementedException ();
  896. }
  897. void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
  898. {
  899. throw new NotImplementedException ();
  900. }
  901. void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
  902. {
  903. throw new NotImplementedException ();
  904. }
  905. void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
  906. {
  907. throw new NotImplementedException ();
  908. }
  909. }
  910. }