1 //
2 // assembly.cs: Assembly declaration and specifications
3 //
4 // Authors:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Marek Safar (marek.safar@gmail.com)
7 //
8 // Copyright 2001, 2002, 2003 Ximian, Inc.
9 // Copyright 2004-2011 Novell, Inc.
10 // Copyright 2011-2013 Xamarin Inc
11 //
12 
13 
14 using System;
15 using System.IO;
16 using System.Collections.Generic;
17 using System.Globalization;
18 using System.Security;
19 using System.Security.Cryptography;
20 using System.Security.Permissions;
21 using Mono.Security.Cryptography;
22 using Mono.CompilerServices.SymbolWriter;
23 using System.Linq;
24 
25 #if STATIC
26 using IKVM.Reflection;
27 using IKVM.Reflection.Emit;
28 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
29 #else
30 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
31 using System.Reflection;
32 using System.Reflection.Emit;
33 #endif
34 
35 namespace Mono.CSharp
36 {
37 	public interface IAssemblyDefinition
38 	{
39 		string FullName { get; }
40 		bool IsCLSCompliant { get; }
41 		bool IsMissing { get; }
42 		string Name { get; }
43 
GetPublicKeyToken()44 		byte[] GetPublicKeyToken ();
IsFriendAssemblyTo(IAssemblyDefinition assembly)45 		bool IsFriendAssemblyTo (IAssemblyDefinition assembly);
46 	}
47 
48 	public class AssemblyReferenceMessageInfo
49 	{
AssemblyReferenceMessageInfo(AssemblyName dependencyName, Action<Report> reportMessage)50 		public AssemblyReferenceMessageInfo (AssemblyName dependencyName, Action<Report> reportMessage)
51 		{
52 			this.DependencyName = dependencyName;
53 			this.ReportMessage = reportMessage;
54 		}
55 
56 		public AssemblyName DependencyName { get; private set; }
57 		public Action<Report> ReportMessage { get; private set; }
58 	}
59 
60 	public abstract class AssemblyDefinition : IAssemblyDefinition
61 	{
62 		// TODO: make it private and move all builder based methods here
63 		public AssemblyBuilder Builder;
64 		protected AssemblyBuilderExtension builder_extra;
65 		MonoSymbolFile symbol_writer;
66 
67 		bool is_cls_compliant;
68 		bool wrap_non_exception_throws;
69 		bool wrap_non_exception_throws_custom;
70 		bool has_user_debuggable;
71 
72 		protected ModuleContainer module;
73 		readonly string name;
74 		protected readonly string file_name;
75 
76 		byte[] public_key, public_key_token;
77 		bool delay_sign;
78 
79 		// Holds private/public key pair when private key
80 		// was available
81 		StrongNameKeyPair private_key;
82 
83 		Attribute cls_attribute;
84 		Method entry_point;
85 
86 		protected List<ImportedModuleDefinition> added_modules;
87 		SecurityType declarative_security;
88 		Dictionary<ITypeDefinition, Attribute> emitted_forwarders;
89 		AssemblyAttributesPlaceholder module_target_attrs;
90 
91 		// Win32 version info values
92 		string vi_product, vi_product_version, vi_company, vi_copyright, vi_trademark;
93 		string pa_file_version, pa_assembly_version;
94 
AssemblyDefinition(ModuleContainer module, string name)95 		protected AssemblyDefinition (ModuleContainer module, string name)
96 		{
97 			this.module = module;
98 			this.name = Path.GetFileNameWithoutExtension (name);
99 
100 			wrap_non_exception_throws = true;
101 
102 			delay_sign = Compiler.Settings.StrongNameDelaySign;
103 
104 			//
105 			// Load strong name key early enough for assembly importer to be able to
106 			// use the keys for InternalsVisibleTo
107 			// This should go somewhere close to ReferencesLoading but don't have the place yet
108 			//
109 			if (Compiler.Settings.HasKeyFileOrContainer) {
110 				LoadPublicKey (Compiler.Settings.StrongNameKeyFile, Compiler.Settings.StrongNameKeyContainer);
111 			}
112 		}
113 
AssemblyDefinition(ModuleContainer module, string name, string fileName)114 		protected AssemblyDefinition (ModuleContainer module, string name, string fileName)
115 			: this (module, name)
116 		{
117 			this.file_name = fileName;
118 		}
119 
120 		#region Properties
121 
122 		public Attribute CLSCompliantAttribute {
123 			get {
124 				return cls_attribute;
125 			}
126 		}
127 
128 		public CompilerContext Compiler {
129 			get {
130 				return module.Compiler;
131 			}
132 		}
133 
134 		//
135 		// Assembly entry point, aka Main method
136 		//
137 		public Method EntryPoint {
138 			get {
139 				return entry_point;
140 			}
141 			set {
142 				entry_point = value;
143 			}
144 		}
145 
146 		public string FullName {
147 			get {
148 				return Builder.FullName;
149 			}
150 		}
151 
152 		public bool HasCLSCompliantAttribute {
153 			get {
154 				return cls_attribute != null;
155 			}
156 		}
157 
158 		// TODO: This should not exist here but will require more changes
159 		public MetadataImporter Importer {
160 		    get; set;
161 		}
162 
163 		public bool IsCLSCompliant {
164 			get {
165 				return is_cls_compliant;
166 			}
167 		}
168 
169 		bool IAssemblyDefinition.IsMissing {
170 			get {
171 				return false;
172 			}
173 		}
174 
175 		public bool IsSatelliteAssembly { get; private set; }
176 
177 		public string Name {
178 			get {
179 				return name;
180 			}
181 		}
182 
183 		public bool WrapNonExceptionThrows {
184 			get {
185 				return wrap_non_exception_throws;
186 			}
187 		}
188 
189 		protected Report Report {
190 			get {
191 				return Compiler.Report;
192 			}
193 		}
194 
195 		public MonoSymbolFile SymbolWriter {
196 			get {
197 				return symbol_writer;
198 			}
199 		}
200 
201 		#endregion
202 
AddModule(ImportedModuleDefinition module)203 		public void AddModule (ImportedModuleDefinition module)
204 		{
205 			if (added_modules == null) {
206 				added_modules = new List<ImportedModuleDefinition> ();
207 				added_modules.Add (module);
208 			}
209 		}
210 
ApplyAttributeBuilder(Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)211 		public void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
212 		{
213 			if (a.IsValidSecurityAttribute ()) {
214 				a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
215 				return;
216 			}
217 
218 			if (a.Type == pa.AssemblyCulture) {
219 				string value = a.GetString ();
220 				if (value == null || value.Length == 0)
221 					return;
222 
223 				if (Compiler.Settings.Target == Target.Exe) {
224 					Report.Error (7059, a.Location, "Executables cannot be satellite assemblies. Remove the attribute or keep it empty");
225 					return;
226 				}
227 
228 				if (value == "neutral")
229 					value = "";
230 
231 				if (Compiler.Settings.Target == Target.Module) {
232 					SetCustomAttribute (ctor, cdata);
233 				} else {
234 					builder_extra.SetCulture (value, a.Location);
235 				}
236 
237 				IsSatelliteAssembly = true;
238 				return;
239 			}
240 
241 			if (a.Type == pa.AssemblyVersion) {
242 				string value = a.GetString ();
243 				if (value == null || value.Length == 0)
244 					return;
245 
246 				var vinfo = IsValidAssemblyVersion (value, true);
247 				if (vinfo == null) {
248 					Report.Error (7034, a.Location, "The specified version string `{0}' does not conform to the required format - major[.minor[.build[.revision]]]",
249 						value);
250 					return;
251 				}
252 
253 				if (Compiler.Settings.Target == Target.Module) {
254 					SetCustomAttribute (ctor, cdata);
255 				} else {
256 					builder_extra.SetVersion (vinfo, a.Location);
257 					pa_assembly_version = vinfo.ToString ();
258 				}
259 
260 				return;
261 			}
262 
263 			if (a.Type == pa.AssemblyAlgorithmId) {
264 				const int pos = 2; // skip CA header
265 				uint alg = (uint) cdata [pos];
266 				alg |= ((uint) cdata [pos + 1]) << 8;
267 				alg |= ((uint) cdata [pos + 2]) << 16;
268 				alg |= ((uint) cdata [pos + 3]) << 24;
269 
270 				if (Compiler.Settings.Target == Target.Module) {
271 					SetCustomAttribute (ctor, cdata);
272 				} else {
273 					builder_extra.SetAlgorithmId (alg, a.Location);
274 				}
275 
276 				return;
277 			}
278 
279 			if (a.Type == pa.AssemblyFlags) {
280 				const int pos = 2; // skip CA header
281 				uint flags = (uint) cdata[pos];
282 				flags |= ((uint) cdata [pos + 1]) << 8;
283 				flags |= ((uint) cdata [pos + 2]) << 16;
284 				flags |= ((uint) cdata [pos + 3]) << 24;
285 
286 				// Ignore set PublicKey flag if assembly is not strongnamed
287 				if ((flags & (uint) AssemblyNameFlags.PublicKey) != 0 && public_key == null)
288 					flags &= ~(uint) AssemblyNameFlags.PublicKey;
289 
290 				if (Compiler.Settings.Target == Target.Module) {
291 					SetCustomAttribute (ctor, cdata);
292 				} else {
293 					builder_extra.SetFlags (flags, a.Location);
294 				}
295 
296 				return;
297 			}
298 
299 			if (a.Type == pa.TypeForwarder) {
300 				TypeSpec t = a.GetArgumentType ();
301 				if (t == null || TypeManager.HasElementType (t)) {
302 					Report.Error (735, a.Location, "Invalid type specified as an argument for TypeForwardedTo attribute");
303 					return;
304 				}
305 
306 				if (emitted_forwarders == null) {
307 					emitted_forwarders = new Dictionary<ITypeDefinition, Attribute> ();
308 				} else if (emitted_forwarders.ContainsKey (t.MemberDefinition)) {
309 					Report.SymbolRelatedToPreviousError (emitted_forwarders[t.MemberDefinition].Location, null);
310 					Report.Error (739, a.Location, "A duplicate type forward of type `{0}'",
311 						t.GetSignatureForError ());
312 					return;
313 				}
314 
315 				emitted_forwarders.Add (t.MemberDefinition, a);
316 
317 				if (t.MemberDefinition.DeclaringAssembly == this) {
318 					Report.SymbolRelatedToPreviousError (t);
319 					Report.Error (729, a.Location, "Cannot forward type `{0}' because it is defined in this assembly",
320 						t.GetSignatureForError ());
321 					return;
322 				}
323 
324 				if (t.IsNested) {
325 					Report.Error (730, a.Location, "Cannot forward type `{0}' because it is a nested type",
326 						t.GetSignatureForError ());
327 					return;
328 				}
329 
330 				AddTypeForwarders (t, a.Location);
331 				return;
332 			}
333 
334 			if (a.Type == pa.Extension) {
335 				a.Error_MisusedExtensionAttribute ();
336 				return;
337 			}
338 
339 			if (a.Type == pa.InternalsVisibleTo) {
340 				string assembly_name = a.GetString ();
341 				if (assembly_name == null) {
342 					Report.Error (7030, a.Location, "Friend assembly reference cannot have `null' value");
343 					return;
344 				}
345 
346 				if (assembly_name.Length == 0)
347 					return;
348 #if STATIC
349 				ParsedAssemblyName aname;
350 				ParseAssemblyResult r = Fusion.ParseAssemblyName (assembly_name, out aname);
351 				if (r != ParseAssemblyResult.OK) {
352 					Report.Warning (1700, 3, a.Location, "Friend assembly reference `{0}' is invalid and cannot be resolved",
353 						assembly_name);
354 					return;
355 				}
356 
357 				if (aname.Version != null || aname.Culture != null || aname.ProcessorArchitecture != ProcessorArchitecture.None) {
358 					Report.Error (1725, a.Location,
359 						"Friend assembly reference `{0}' is invalid. InternalsVisibleTo declarations cannot have a version, culture or processor architecture specified",
360 						assembly_name);
361 
362 					return;
363 				}
364 
365 				if (public_key != null && !aname.HasPublicKey) {
366 					Report.Error (1726, a.Location,
367 						"Friend assembly reference `{0}' is invalid. Strong named assemblies must specify a public key in their InternalsVisibleTo declarations",
368 						assembly_name);
369 					return;
370 				}
371 #endif
372 			} else if (a.Type == pa.RuntimeCompatibility) {
373 				wrap_non_exception_throws_custom = true;
374 			} else if (a.Type == pa.AssemblyFileVersion) {
375 				pa_file_version = a.GetString ();
376 				if (string.IsNullOrEmpty (pa_file_version) || IsValidAssemblyVersion (pa_file_version, false) == null) {
377 					Report.Warning (7035, 1, a.Location, "The specified version string `{0}' does not conform to the recommended format major.minor.build.revision",
378 					                pa_file_version, a.Name);
379 					return;
380 				}
381 
382 				// File version info decoding from blob is not supported
383 				var cab = new CustomAttributeBuilder ((ConstructorInfo)ctor.GetMetaInfo (), new object [] { pa_file_version });
384 				Builder.SetCustomAttribute (cab);
385 				return;
386 			} else if (a.Type == pa.AssemblyProduct) {
387 				vi_product = a.GetString ();
388 			} else if (a.Type == pa.AssemblyCompany) {
389 				vi_company = a.GetString ();
390 			} else if (a.Type == pa.AssemblyCopyright) {
391 				vi_copyright = a.GetString ();
392 			} else if (a.Type == pa.AssemblyTrademark) {
393 				vi_trademark = a.GetString ();
394 			} else if (a.Type == pa.Debuggable) {
395 				has_user_debuggable = true;
396 			} else if (a.Type == pa.AssemblyInformationalVersion) {
397 				vi_product_version = a.GetString ();
398 			}
399 
400 			//
401 			// Win32 version info attributes AssemblyDescription and AssemblyTitle cannot be
402 			// set using public API and because we have blob like attributes we need to use
403 			// special option DecodeVersionInfoAttributeBlobs to support values extraction
404 			//
405 
406 			SetCustomAttribute (ctor, cdata);
407 		}
408 
AddTypeForwarders(TypeSpec type, Location loc)409 		void AddTypeForwarders (TypeSpec type, Location loc)
410 		{
411 			builder_extra.AddTypeForwarder (type.GetDefinition (), loc);
412 
413 			var ntypes = MemberCache.GetDeclaredNestedTypes (type);
414 			if (ntypes == null)
415 				return;
416 
417 			foreach (var nested in ntypes) {
418 				if (nested.IsPrivate)
419 					continue;
420 
421 				AddTypeForwarders (nested, loc);
422 			}
423 		}
424 
425 		//
426 		// When using assembly public key attributes InternalsVisibleTo key
427 		// was not checked, we have to do it later when we actually know what
428 		// our public key token is
429 		//
CheckReferencesPublicToken()430 		void CheckReferencesPublicToken ()
431 		{
432 			var references = builder_extra.GetReferencedAssemblies ();
433 			foreach (var an in references) {
434 				if (public_key != null && an.GetPublicKey ().Length == 0) {
435 					Report.Error (1577, "Referenced assembly `{0}' does not have a strong name",
436 						an.FullName);
437 				}
438 
439 				var ci = an.CultureInfo;
440 				if (!ci.Equals (CultureInfo.InvariantCulture)) {
441 					Report.Warning (8009, 1, "Referenced assembly `{0}' has different culture setting of `{1}'",
442 						an.Name, ci.Name);
443 				}
444 
445 				var ia = Importer.GetImportedAssemblyDefinition (an);
446 				if (ia == null)
447 					continue;
448 
449 				var an_references = GetNotUnifiedReferences (an);
450 				if (an_references != null) {
451 					foreach (var r in an_references) {
452 						//
453 						// Secondary check when assembly references is resolved but not used. For example
454 						// due to type-forwarding
455 						//
456 						if (references.Any (l => l.Name == r.DependencyName.Name)) {
457 							r.ReportMessage (Report);
458 						}
459 					}
460 				}
461 
462 				if (!ia.IsFriendAssemblyTo (this))
463 					continue;
464 
465 				var attr = ia.GetAssemblyVisibleToName (this);
466 				var atoken = attr.GetPublicKeyToken ();
467 
468 				if (ArrayComparer.IsEqual (GetPublicKeyToken (), atoken))
469 					continue;
470 
471 				Report.SymbolRelatedToPreviousError (ia.Location);
472 				Report.Error (281,
473 					"Friend access was granted to `{0}', but the output assembly is named `{1}'. Try adding a reference to `{0}' or change the output assembly name to match it",
474 					attr.FullName, FullName);
475 			}
476 		}
477 
CreateAssemblyName()478 		protected AssemblyName CreateAssemblyName ()
479 		{
480 			var an = new AssemblyName (name);
481 
482 			if (public_key != null && Compiler.Settings.Target != Target.Module) {
483 				if (delay_sign) {
484 					an.SetPublicKey (public_key);
485 				} else {
486 					if (public_key.Length == 16) {
487 						Report.Error (1606, "Could not sign the assembly. ECMA key can only be used to delay-sign assemblies");
488 					} else if (private_key == null) {
489 						Error_AssemblySigning ("The specified key file does not have a private key");
490 					} else {
491 						an.KeyPair = private_key;
492 					}
493 				}
494 			}
495 
496 			return an;
497 		}
498 
CreateModuleBuilder()499 		public virtual ModuleBuilder CreateModuleBuilder ()
500 		{
501 			if (file_name == null)
502 				throw new NotSupportedException ("transient module in static assembly");
503 
504 			var module_name = Path.GetFileName (file_name);
505 
506 			// Always initialize module without symbolInfo. We could be framework dependent
507 			// but returned ISymbolWriter does not have all what we need therefore some
508 			// adaptor will be needed for now we alwayas emit MDB format when generating
509 			// debug info
510 			return Builder.DefineDynamicModule (module_name, module_name, false);
511 		}
512 
Emit()513 		public virtual void Emit ()
514 		{
515 			if (Compiler.Settings.Target == Target.Module) {
516 				module_target_attrs = new AssemblyAttributesPlaceholder (module, name);
517 				module_target_attrs.CreateContainer ();
518 				module_target_attrs.DefineContainer ();
519 				module_target_attrs.Define ();
520 				module.AddCompilerGeneratedClass (module_target_attrs);
521 			} else if (added_modules != null) {
522 				ReadModulesAssemblyAttributes ();
523 			}
524 
525 			if (Compiler.Settings.GenerateDebugInfo) {
526 				symbol_writer = new MonoSymbolFile ();
527 			}
528 
529 			module.EmitContainer ();
530 
531 			if (module.HasExtensionMethod) {
532 				var pa = module.PredefinedAttributes.Extension;
533 				if (pa.IsDefined) {
534 					SetCustomAttribute (pa.Constructor, AttributeEncoder.Empty);
535 				}
536 			}
537 
538 			if (!IsSatelliteAssembly) {
539 				if (!has_user_debuggable && Compiler.Settings.GenerateDebugInfo) {
540 					var pa = module.PredefinedAttributes.Debuggable;
541 					if (pa.IsDefined) {
542 						var modes = System.Diagnostics.DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints;
543 						if (!Compiler.Settings.Optimize)
544 							modes |= System.Diagnostics.DebuggableAttribute.DebuggingModes.DisableOptimizations;
545 
546 						pa.EmitAttribute (Builder, modes);
547 					}
548 				}
549 
550 				if (!wrap_non_exception_throws_custom) {
551 					PredefinedAttribute pa = module.PredefinedAttributes.RuntimeCompatibility;
552 					if (pa.IsDefined && pa.ResolveBuilder ()) {
553 						var prop = module.PredefinedMembers.RuntimeCompatibilityWrapNonExceptionThrows.Get ();
554 						if (prop != null) {
555 							AttributeEncoder encoder = new AttributeEncoder ();
556 							encoder.EncodeNamedPropertyArgument (prop, new BoolLiteral (Compiler.BuiltinTypes, true, Location.Null));
557 							SetCustomAttribute (pa.Constructor, encoder.ToArray ());
558 						}
559 					}
560 				}
561 
562 				if (declarative_security != null) {
563 #if STATIC
564 					foreach (var entry in declarative_security) {
565 						Builder.__AddDeclarativeSecurity (entry);
566 					}
567 #else
568 					throw new NotSupportedException ("Assembly-level security");
569 #endif
570 				}
571 			}
572 
573 			CheckReferencesPublicToken ();
574 
575 			SetEntryPoint ();
576 		}
577 
GetPublicKeyToken()578 		public byte[] GetPublicKeyToken ()
579 		{
580 			if (public_key == null || public_key_token != null)
581 				return public_key_token;
582 
583 			HashAlgorithm ha = SHA1.Create ();
584 			byte[] hash = ha.ComputeHash (public_key);
585 			// we need the last 8 bytes in reverse order
586 			public_key_token = new byte[8];
587 			Buffer.BlockCopy (hash, hash.Length - 8, public_key_token, 0, 8);
588 			Array.Reverse (public_key_token, 0, 8);
589 			return public_key_token;
590 		}
591 
GetNotUnifiedReferences(AssemblyName assemblyName)592 		protected virtual List<AssemblyReferenceMessageInfo> GetNotUnifiedReferences (AssemblyName assemblyName)
593 		{
594 			return null;
595 		}
596 
597 		//
598 		// Either keyFile or keyContainer has to be non-null
599 		//
LoadPublicKey(string keyFile, string keyContainer)600 		void LoadPublicKey (string keyFile, string keyContainer)
601 		{
602 			if (keyContainer != null) {
603 				try {
604 					private_key = new StrongNameKeyPair (keyContainer);
605 					public_key = private_key.PublicKey;
606 				} catch {
607 					Error_AssemblySigning ("The specified key container `" + keyContainer + "' does not exist");
608 				}
609 
610 				return;
611 			}
612 
613 			bool key_file_exists = File.Exists (keyFile);
614 
615 			//
616 			// For attribute based KeyFile do additional lookup
617 			// in output assembly path
618 			//
619 			if (!key_file_exists && Compiler.Settings.StrongNameKeyFile == null) {
620 				//
621 				// The key file can be relative to output assembly
622 				//
623 				string test_path = Path.Combine (Path.GetDirectoryName (file_name), keyFile);
624 				key_file_exists = File.Exists (test_path);
625 				if (key_file_exists)
626 					keyFile = test_path;
627 			}
628 
629 			if (!key_file_exists) {
630 				Error_AssemblySigning ("The specified key file `" + keyFile + "' does not exist");
631 				return;
632 			}
633 
634 			using (FileStream fs = new FileStream (keyFile, FileMode.Open, FileAccess.Read)) {
635 				byte[] snkeypair = new byte[fs.Length];
636 				fs.Read (snkeypair, 0, snkeypair.Length);
637 
638 				// check for ECMA key
639 				if (snkeypair.Length == 16) {
640 					public_key = snkeypair;
641 					return;
642 				}
643 
644 				try {
645 					// take it, with or without, a private key
646 					RSA rsa = CryptoConvert.FromCapiKeyBlob (snkeypair);
647 					// and make sure we only feed the public part to Sys.Ref
648 					byte[] publickey = CryptoConvert.ToCapiPublicKeyBlob (rsa);
649 
650 					// AssemblyName.SetPublicKey requires an additional header
651 					byte[] publicKeyHeader = new byte[8] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00 };
652 
653 					// Encode public key
654 					public_key = new byte[12 + publickey.Length];
655 					Buffer.BlockCopy (publicKeyHeader, 0, public_key, 0, publicKeyHeader.Length);
656 
657 					// Length of Public Key (in bytes)
658 					int lastPart = public_key.Length - 12;
659 					public_key[8] = (byte) (lastPart & 0xFF);
660 					public_key[9] = (byte) ((lastPart >> 8) & 0xFF);
661 					public_key[10] = (byte) ((lastPart >> 16) & 0xFF);
662 					public_key[11] = (byte) ((lastPart >> 24) & 0xFF);
663 
664 					Buffer.BlockCopy (publickey, 0, public_key, 12, publickey.Length);
665 				} catch {
666 					Error_AssemblySigning ("The specified key file `" + keyFile + "' has incorrect format");
667 					return;
668 				}
669 
670 				if (delay_sign)
671 					return;
672 
673 				try {
674 					// TODO: Is there better way to test for a private key presence ?
675 					CryptoConvert.FromCapiPrivateKeyBlob (snkeypair);
676 					private_key = new StrongNameKeyPair (snkeypair);
677 				} catch { }
678 			}
679 		}
680 
ReadModulesAssemblyAttributes()681 		void ReadModulesAssemblyAttributes ()
682 		{
683 			foreach (var m in added_modules) {
684 				var cattrs = m.ReadAssemblyAttributes ();
685 				if (cattrs == null)
686 					continue;
687 
688 				module.OptAttributes.AddAttributes (cattrs);
689 			}
690 		}
691 
Resolve()692 		public void Resolve ()
693 		{
694 			if (Compiler.Settings.Unsafe && module.PredefinedTypes.SecurityAction.Define ()) {
695 				//
696 				// Emits [assembly: SecurityPermissionAttribute (SecurityAction.RequestMinimum, SkipVerification = true)]
697 				// when -unsafe option was specified
698 				//
699 				Location loc = Location.Null;
700 
701 				MemberAccess system_security_permissions = new MemberAccess (new MemberAccess (
702 					new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Security", loc), "Permissions", loc);
703 
704 				var req_min = module.PredefinedMembers.SecurityActionRequestMinimum.Resolve (loc);
705 
706 				Arguments pos = new Arguments (1);
707 				pos.Add (new Argument (req_min.GetConstant (null)));
708 
709 				Arguments named = new Arguments (1);
710 				named.Add (new NamedArgument ("SkipVerification", loc, new BoolLiteral (Compiler.BuiltinTypes, true, loc)));
711 
712 				Attribute g = new Attribute ("assembly",
713 					new MemberAccess (system_security_permissions, "SecurityPermissionAttribute"),
714 					new Arguments[] { pos, named }, loc, false);
715 				g.AttachTo (module, module);
716 
717 				// Disable no-location warnings (e.g. obsolete) for compiler generated attribute
718 				Compiler.Report.DisableReporting ();
719 				try {
720 					var ctor = g.Resolve ();
721 					if (ctor != null) {
722 						g.ExtractSecurityPermissionSet (ctor, ref declarative_security);
723 					}
724 				} finally {
725 					Compiler.Report.EnableReporting ();
726 				}
727 			}
728 
729 			if (module.OptAttributes == null)
730 				return;
731 
732 			// Ensure that we only have GlobalAttributes, since the Search isn't safe with other types.
733 			if (!module.OptAttributes.CheckTargets())
734 				return;
735 
736 			cls_attribute = module.ResolveAssemblyAttribute (module.PredefinedAttributes.CLSCompliant);
737 
738 			if (cls_attribute != null) {
739 				is_cls_compliant = cls_attribute.GetClsCompliantAttributeValue ();
740 			}
741 
742 			if (added_modules != null && Compiler.Settings.VerifyClsCompliance && is_cls_compliant) {
743 				foreach (var m in added_modules) {
744 					if (!m.IsCLSCompliant) {
745 						Report.Error (3013,
746 							"Added modules must be marked with the CLSCompliant attribute to match the assembly",
747 							m.Name);
748 					}
749 				}
750 			}
751 
752 			Attribute a = module.ResolveAssemblyAttribute (module.PredefinedAttributes.RuntimeCompatibility);
753 			if (a != null) {
754 				var val = a.GetNamedValue ("WrapNonExceptionThrows") as BoolConstant;
755 				if (val != null)
756 					wrap_non_exception_throws = val.Value;
757 			}
758 		}
759 
ResolveAssemblySecurityAttributes()760 		protected void ResolveAssemblySecurityAttributes ()
761 		{
762 			string key_file = null;
763 			string key_container = null;
764 
765 			if (module.OptAttributes != null) {
766 				foreach (Attribute a in module.OptAttributes.Attrs) {
767 					// cannot rely on any resolve-based members before you call Resolve
768 					if (a.ExplicitTarget != "assembly")
769 						continue;
770 
771 					// TODO: This code is buggy: comparing Attribute name without resolving is wrong.
772 					//       However, this is invoked by CodeGen.Init, when none of the namespaces
773 					//       are loaded yet.
774 					// TODO: Does not handle quoted attributes properly
775 					switch (a.Name) {
776 					case "AssemblyKeyFile":
777 					case "AssemblyKeyFileAttribute":
778 					case "System.Reflection.AssemblyKeyFileAttribute":
779 						if (Compiler.Settings.StrongNameKeyFile != null) {
780 							Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ());
781 							Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module",
782 									"keyfile", "System.Reflection.AssemblyKeyFileAttribute");
783 						} else {
784 							string value = a.GetString ();
785 							if (!string.IsNullOrEmpty (value)) {
786 								Error_ObsoleteSecurityAttribute (a, "keyfile");
787 								key_file = value;
788 							}
789 						}
790 						break;
791 					case "AssemblyKeyName":
792 					case "AssemblyKeyNameAttribute":
793 					case "System.Reflection.AssemblyKeyNameAttribute":
794 						if (Compiler.Settings.StrongNameKeyContainer != null) {
795 							Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ());
796 							Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module",
797 									"keycontainer", "System.Reflection.AssemblyKeyNameAttribute");
798 						} else {
799 							string value = a.GetString ();
800 							if (!string.IsNullOrEmpty (value)) {
801 								Error_ObsoleteSecurityAttribute (a, "keycontainer");
802 								key_container = value;
803 							}
804 						}
805 						break;
806 					case "AssemblyDelaySign":
807 					case "AssemblyDelaySignAttribute":
808 					case "System.Reflection.AssemblyDelaySignAttribute":
809 						bool b = a.GetBoolean ();
810 						if (b) {
811 							Error_ObsoleteSecurityAttribute (a, "delaysign");
812 						}
813 
814 						delay_sign = b;
815 						break;
816 					}
817 				}
818 			}
819 
820 			// We came here only to report assembly attributes warnings
821 			if (public_key != null)
822 				return;
823 
824 			//
825 			// Load the strong key file found in attributes when no
826 			// command line key was given
827 			//
828 			if (key_file != null || key_container != null) {
829 				LoadPublicKey (key_file, key_container);
830 			} else if (delay_sign) {
831 				Report.Warning (1607, 1, "Delay signing was requested but no key file was given");
832 			}
833 		}
834 
EmbedResources()835 		public void EmbedResources ()
836 		{
837 			//
838 			// Add Win32 resources
839 			//
840 			if (Compiler.Settings.Win32ResourceFile != null) {
841 				Builder.DefineUnmanagedResource (Compiler.Settings.Win32ResourceFile);
842 			} else {
843 				Builder.DefineVersionInfoResource (vi_product,
844 				                                   vi_product_version ?? pa_file_version ?? pa_assembly_version,
845 				                                   vi_company,
846 				                                   vi_copyright,
847 				                                   vi_trademark);
848 			}
849 
850 			if (Compiler.Settings.Win32IconFile != null) {
851 				builder_extra.DefineWin32IconResource (Compiler.Settings.Win32IconFile);
852 			}
853 
854 			if (Compiler.Settings.Resources != null) {
855 				if (Compiler.Settings.Target == Target.Module) {
856 					Report.Error (1507, "Cannot link resource file when building a module");
857 				} else {
858 					int counter = 0;
859 					foreach (var res in Compiler.Settings.Resources) {
860 						if (!File.Exists (res.FileName)) {
861 							Report.Error (1566, "Error reading resource file `{0}'", res.FileName);
862 							continue;
863 						}
864 
865 						if (res.IsEmbeded) {
866 							Stream stream;
867 							if (counter++ < 10) {
868 								stream = File.OpenRead (res.FileName);
869 							} else {
870 								// TODO: SRE API requires resource stream to be available during AssemblyBuilder::Save
871 								// we workaround it by reading everything into memory to compile projects with
872 								// many embedded resource (over 3500) references
873 								stream = new MemoryStream (File.ReadAllBytes (res.FileName));
874 							}
875 
876 							module.Builder.DefineManifestResource (res.Name, stream, res.Attributes);
877 						} else {
878 							Builder.AddResourceFile (res.Name, Path.GetFileName (res.FileName), res.Attributes);
879 						}
880 					}
881 				}
882 			}
883 		}
884 
Save()885 		public void Save ()
886 		{
887 			PortableExecutableKinds pekind = PortableExecutableKinds.ILOnly;
888 			ImageFileMachine machine;
889 
890 			switch (Compiler.Settings.Platform) {
891 			case Platform.X86:
892 				pekind |= PortableExecutableKinds.Required32Bit;
893 				machine = ImageFileMachine.I386;
894 				break;
895 			case Platform.X64:
896 				pekind |= PortableExecutableKinds.PE32Plus;
897 				machine = ImageFileMachine.AMD64;
898 				break;
899 			case Platform.IA64:
900 				machine = ImageFileMachine.IA64;
901 				break;
902 			case Platform.AnyCPU32Preferred:
903 #if STATIC
904 				pekind |= PortableExecutableKinds.Preferred32Bit;
905 				machine = ImageFileMachine.I386;
906 				break;
907 #else
908 				throw new NotSupportedException ();
909 #endif
910 			case Platform.Arm:
911 #if STATIC
912 				machine = ImageFileMachine.ARM;
913 				break;
914 #else
915 				throw new NotSupportedException ();
916 #endif
917 			case Platform.AnyCPU:
918 			default:
919 				machine = ImageFileMachine.I386;
920 				break;
921 			}
922 
923 			Compiler.TimeReporter.Start (TimeReporter.TimerType.OutputSave);
924 			try {
925 				if (Compiler.Settings.Target == Target.Module) {
926 					SaveModule (pekind, machine);
927 				} else {
928 					Builder.Save (module.Builder.ScopeName, pekind, machine);
929 				}
930 			} catch (ArgumentOutOfRangeException) {
931 				Report.Error (16, "Output file `{0}' exceeds the 4GB limit", name);
932 			} catch (Exception e) {
933 				Report.Error (16, "Could not write to file `{0}'. {1}", name, e.Message);
934 			}
935 			Compiler.TimeReporter.Stop (TimeReporter.TimerType.OutputSave);
936 
937 			// Save debug symbols file
938 			if (symbol_writer != null && Compiler.Report.Errors == 0) {
939 				// TODO: it should run in parallel
940 				Compiler.TimeReporter.Start (TimeReporter.TimerType.DebugSave);
941 
942 				var filename = file_name + ".mdb";
943 				try {
944 					// We mmap the file, so unlink the previous version since it may be in use
945 					File.Delete (filename);
946 				} catch {
947 					// We can safely ignore
948 				}
949 
950 				module.WriteDebugSymbol (symbol_writer);
951 
952 				using (FileStream fs = new FileStream (filename, FileMode.Create, FileAccess.Write)) {
953 					symbol_writer.CreateSymbolFile (module.Builder.ModuleVersionId, fs);
954 				}
955 
956 				Compiler.TimeReporter.Stop (TimeReporter.TimerType.DebugSave);
957 			}
958 		}
959 
SaveModule(PortableExecutableKinds pekind, ImageFileMachine machine)960 		protected virtual void SaveModule (PortableExecutableKinds pekind, ImageFileMachine machine)
961 		{
962 			Report.RuntimeMissingSupport (Location.Null, "-target:module");
963 		}
964 
SetCustomAttribute(MethodSpec ctor, byte[] data)965 		void SetCustomAttribute (MethodSpec ctor, byte[] data)
966 		{
967 			if (module_target_attrs != null)
968 				module_target_attrs.AddAssemblyAttribute (ctor, data);
969 			else
970 				Builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), data);
971 		}
972 
SetEntryPoint()973 		void SetEntryPoint ()
974 		{
975 			if (!Compiler.Settings.NeedsEntryPoint) {
976 				if (Compiler.Settings.MainClass != null)
977 					Report.Error (2017, "Cannot specify -main if building a module or library");
978 
979 				return;
980 			}
981 
982 			PEFileKinds file_kind;
983 
984 			switch (Compiler.Settings.Target) {
985 			case Target.Library:
986 			case Target.Module:
987 				file_kind = PEFileKinds.Dll;
988 				break;
989 			case Target.WinExe:
990 				file_kind = PEFileKinds.WindowApplication;
991 				break;
992 			default:
993 				file_kind = PEFileKinds.ConsoleApplication;
994 				break;
995 			}
996 
997 			if (entry_point == null) {
998 				string main_class = Compiler.Settings.MainClass;
999 				if (main_class != null) {
1000 					// TODO: Handle dotted names
1001 					var texpr = module.GlobalRootNamespace.LookupType (module, main_class, 0, LookupMode.Probing, Location.Null);
1002 					if (texpr == null) {
1003 						Report.Error (1555, "Could not find `{0}' specified for Main method", main_class);
1004 						return;
1005 					}
1006 
1007 					var mtype = texpr.MemberDefinition as ClassOrStruct;
1008 					if (mtype == null) {
1009 						Report.Error (1556, "`{0}' specified for Main method must be a valid class or struct", main_class);
1010 						return;
1011 					}
1012 
1013 					Report.Error (1558, mtype.Location, "`{0}' does not have a suitable static Main method", mtype.GetSignatureForError ());
1014 				} else {
1015 					string pname = file_name == null ? name : Path.GetFileName (file_name);
1016 					Report.Error (5001, "Program `{0}' does not contain a static `Main' method suitable for an entry point",
1017 						pname);
1018 				}
1019 
1020 				return;
1021 			}
1022 
1023 			Builder.SetEntryPoint (entry_point.MethodBuilder, file_kind);
1024 		}
1025 
Error_ObsoleteSecurityAttribute(Attribute a, string option)1026 		void Error_ObsoleteSecurityAttribute (Attribute a, string option)
1027 		{
1028 			Report.Warning (1699, 1, a.Location,
1029 				"Use compiler option `{0}' or appropriate project settings instead of `{1}' attribute",
1030 				option, a.Name);
1031 		}
1032 
Error_AssemblySigning(string text)1033 		void Error_AssemblySigning (string text)
1034 		{
1035 			Report.Error (1548, "Error during assembly signing. " + text);
1036 		}
1037 
IsFriendAssemblyTo(IAssemblyDefinition assembly)1038 		public bool IsFriendAssemblyTo (IAssemblyDefinition assembly)
1039 		{
1040 			return false;
1041 		}
1042 
IsValidAssemblyVersion(string version, bool allowGenerated)1043 		static Version IsValidAssemblyVersion (string version, bool allowGenerated)
1044 		{
1045 			string[] parts = version.Split ('.');
1046 			if (parts.Length < 1 || parts.Length > 4)
1047 				return null;
1048 
1049 			var values = new int[4];
1050 			for (int i = 0; i < parts.Length; ++i) {
1051 				if (!int.TryParse (parts[i], out values[i])) {
1052 					if (parts[i].Length == 1 && parts[i][0] == '*' && allowGenerated) {
1053 						if (i == 2) {
1054 							// Nothing can follow *
1055 							if (parts.Length > 3)
1056 								return null;
1057 
1058 							// Generate Build value based on days since 1/1/2000
1059 							TimeSpan days = DateTime.Today - new DateTime (2000, 1, 1);
1060 							values[i] = System.Math.Max (days.Days, 0);
1061 							i = 3;
1062 						}
1063 
1064 						if (i == 3) {
1065 							// Generate Revision value based on every other second today
1066 							var seconds = DateTime.Now - DateTime.Today;
1067 							values[i] = (int) seconds.TotalSeconds / 2;
1068 							continue;
1069 						}
1070 					}
1071 
1072 					return null;
1073 				}
1074 
1075 				if (values[i] > ushort.MaxValue)
1076 					return null;
1077 			}
1078 
1079 			return new Version (values[0], values[1], values[2], values[3]);
1080 		}
1081 	}
1082 
1083 	public class AssemblyResource : IEquatable<AssemblyResource>
1084 	{
AssemblyResource(string fileName, string name)1085 		public AssemblyResource (string fileName, string name)
1086 			: this (fileName, name, false)
1087 		{
1088 		}
1089 
AssemblyResource(string fileName, string name, bool isPrivate)1090 		public AssemblyResource (string fileName, string name, bool isPrivate)
1091 		{
1092 			FileName = fileName;
1093 			Name = name;
1094 			Attributes = isPrivate ? ResourceAttributes.Private : ResourceAttributes.Public;
1095 		}
1096 
1097 		public ResourceAttributes Attributes { get; private set; }
1098 		public string Name { get; private set; }
1099 		public string FileName { get; private set; }
1100 		public bool IsEmbeded { get; set; }
1101 
1102 		#region IEquatable<AssemblyResource> Members
1103 
Equals(AssemblyResource other)1104 		public bool Equals (AssemblyResource other)
1105 		{
1106 			return Name == other.Name;
1107 		}
1108 
1109 		#endregion
1110 	}
1111 
1112 	//
1113 	// A placeholder class for assembly attributes when emitting module
1114 	//
1115 	class AssemblyAttributesPlaceholder : CompilerGeneratedContainer
1116 	{
1117 		static readonly string TypeNamePrefix = "<$AssemblyAttributes${0}>";
1118 		public static readonly string AssemblyFieldName = "attributes";
1119 
1120 		Field assembly;
1121 
AssemblyAttributesPlaceholder(ModuleContainer parent, string outputName)1122 		public AssemblyAttributesPlaceholder (ModuleContainer parent, string outputName)
1123 			: base (parent, new MemberName (GetGeneratedName (outputName)), Modifiers.STATIC | Modifiers.INTERNAL)
1124 		{
1125 			assembly = new Field (this, new TypeExpression (parent.Compiler.BuiltinTypes.Object, Location), Modifiers.PUBLIC | Modifiers.STATIC,
1126 				new MemberName (AssemblyFieldName), null);
1127 
1128 			AddField (assembly);
1129 		}
1130 
AddAssemblyAttribute(MethodSpec ctor, byte[] data)1131 		public void AddAssemblyAttribute (MethodSpec ctor, byte[] data)
1132 		{
1133 			assembly.SetCustomAttribute (ctor, data);
1134 		}
1135 
GetGeneratedName(string outputName)1136 		public static string GetGeneratedName (string outputName)
1137 		{
1138 			return string.Format (TypeNamePrefix, outputName);
1139 		}
1140 	}
1141 
1142 	//
1143 	// Extension to System.Reflection.Emit.AssemblyBuilder to have fully compatible
1144 	// compiler. This is a default implementation for framework System.Reflection.Emit
1145 	// which does not implement any of the methods
1146 	//
1147 	public class AssemblyBuilderExtension
1148 	{
1149 		protected readonly CompilerContext ctx;
1150 
AssemblyBuilderExtension(CompilerContext ctx)1151 		public AssemblyBuilderExtension (CompilerContext ctx)
1152 		{
1153 			this.ctx = ctx;
1154 		}
1155 
AddModule(string module)1156 		public virtual System.Reflection.Module AddModule (string module)
1157 		{
1158 			ctx.Report.RuntimeMissingSupport (Location.Null, "-addmodule");
1159 			return null;
1160 		}
1161 
AddPermissionRequests(PermissionSet[] permissions)1162 		public virtual void AddPermissionRequests (PermissionSet[] permissions)
1163 		{
1164 			ctx.Report.RuntimeMissingSupport (Location.Null, "assembly declarative security");
1165 		}
1166 
AddTypeForwarder(TypeSpec type, Location loc)1167 		public virtual void AddTypeForwarder (TypeSpec type, Location loc)
1168 		{
1169 			ctx.Report.RuntimeMissingSupport (loc, "TypeForwardedToAttribute");
1170 		}
1171 
DefineWin32IconResource(string fileName)1172 		public virtual void DefineWin32IconResource (string fileName)
1173 		{
1174 			ctx.Report.RuntimeMissingSupport (Location.Null, "-win32icon");
1175 		}
1176 
GetReferencedAssemblies()1177 		public virtual AssemblyName[] GetReferencedAssemblies ()
1178 		{
1179 			return null;
1180 		}
1181 
SetAlgorithmId(uint value, Location loc)1182 		public virtual void SetAlgorithmId (uint value, Location loc)
1183 		{
1184 			ctx.Report.RuntimeMissingSupport (loc, "AssemblyAlgorithmIdAttribute");
1185 		}
1186 
SetCulture(string culture, Location loc)1187 		public virtual void SetCulture (string culture, Location loc)
1188 		{
1189 			ctx.Report.RuntimeMissingSupport (loc, "AssemblyCultureAttribute");
1190 		}
1191 
SetFlags(uint flags, Location loc)1192 		public virtual void SetFlags (uint flags, Location loc)
1193 		{
1194 			ctx.Report.RuntimeMissingSupport (loc, "AssemblyFlagsAttribute");
1195 		}
1196 
SetVersion(Version version, Location loc)1197 		public virtual void SetVersion (Version version, Location loc)
1198 		{
1199 			ctx.Report.RuntimeMissingSupport (loc, "AssemblyVersionAttribute");
1200 		}
1201 	}
1202 
1203 	abstract class AssemblyReferencesLoader<T> where T : class
1204 	{
1205 		protected readonly CompilerContext compiler;
1206 
1207 		protected readonly List<string> paths;
1208 
AssemblyReferencesLoader(CompilerContext compiler)1209 		protected AssemblyReferencesLoader (CompilerContext compiler)
1210 		{
1211 			this.compiler = compiler;
1212 
1213 			paths = new List<string> ();
1214 			paths.Add (Directory.GetCurrentDirectory ());
1215 			paths.AddRange (compiler.Settings.ReferencesLookupPaths);
1216 		}
1217 
HasObjectType(T assembly)1218 		public abstract T HasObjectType (T assembly);
GetDefaultReferences()1219 		protected abstract string[] GetDefaultReferences ();
LoadAssemblyFile(string fileName, bool isImplicitReference)1220 		public abstract T LoadAssemblyFile (string fileName, bool isImplicitReference);
LoadReferences(ModuleContainer module)1221 		public abstract void LoadReferences (ModuleContainer module);
1222 
Error_FileNotFound(string fileName)1223 		protected void Error_FileNotFound (string fileName)
1224 		{
1225 			compiler.Report.Error (6, "Metadata file `{0}' could not be found", fileName);
1226 		}
1227 
Error_FileCorrupted(string fileName)1228 		protected void Error_FileCorrupted (string fileName)
1229 		{
1230 			compiler.Report.Error (9, "Metadata file `{0}' does not contain valid metadata", fileName);
1231 		}
1232 
Error_AssemblyIsModule(string fileName)1233 		protected void Error_AssemblyIsModule (string fileName)
1234 		{
1235 			compiler.Report.Error (1509,
1236 				"Referenced assembly file `{0}' is a module. Consider using `-addmodule' option to add the module",
1237 				fileName);
1238 		}
1239 
Error_ModuleIsAssembly(string fileName)1240 		protected void Error_ModuleIsAssembly (string fileName)
1241 		{
1242 			compiler.Report.Error (1542,
1243 				"Added module file `{0}' is an assembly. Consider using `-r' option to reference the file",
1244 				fileName);
1245 		}
1246 
LoadReferencesCore(ModuleContainer module, out T corlib_assembly, out List<Tuple<RootNamespace, T>> loaded)1247 		protected void LoadReferencesCore (ModuleContainer module, out T corlib_assembly, out List<Tuple<RootNamespace, T>> loaded)
1248 		{
1249 			compiler.TimeReporter.Start (TimeReporter.TimerType.ReferencesLoading);
1250 
1251 			loaded = new List<Tuple<RootNamespace, T>> ();
1252 
1253 			//
1254 			// Load mscorlib.dll as the first
1255 			//
1256 			if (module.Compiler.Settings.StdLib) {
1257 				corlib_assembly = LoadAssemblyFile ("mscorlib.dll", true);
1258 			} else {
1259 				corlib_assembly = default (T);
1260 			}
1261 
1262 			T a;
1263 			foreach (string r in module.Compiler.Settings.AssemblyReferences) {
1264 				a = LoadAssemblyFile (r, false);
1265 				if (a == null || EqualityComparer<T>.Default.Equals (a, corlib_assembly))
1266 					continue;
1267 
1268 				var key = Tuple.Create (module.GlobalRootNamespace, a);
1269 				if (loaded.Contains (key))
1270 					continue;
1271 
1272 				loaded.Add (key);
1273 			}
1274 
1275 			if (corlib_assembly == null) {
1276 				//
1277 				// Requires second pass because HasObjectType can trigger assembly load event
1278 				//
1279 				for (int i = 0; i < loaded.Count; ++i) {
1280 					var assembly = loaded [i];
1281 
1282 					//
1283 					// corlib assembly is the first referenced assembly which contains System.Object
1284 					//
1285 					corlib_assembly = HasObjectType (assembly.Item2);
1286 					if (corlib_assembly != null) {
1287 						if (corlib_assembly != assembly.Item2) {
1288 							var ca = corlib_assembly;
1289 							i = loaded.FindIndex (l => l.Item2 == ca);
1290 						}
1291 
1292 						if (i >= 0)
1293 							loaded.RemoveAt (i);
1294 
1295 						break;
1296 					}
1297 				}
1298 			}
1299 
1300 			foreach (var entry in module.Compiler.Settings.AssemblyReferencesAliases) {
1301 				a = LoadAssemblyFile (entry.Item2, false);
1302 				if (a == null)
1303 					continue;
1304 
1305 				var key = Tuple.Create (module.CreateRootNamespace (entry.Item1), a);
1306 				if (loaded.Contains (key))
1307 					continue;
1308 
1309 				loaded.Add (key);
1310 			}
1311 
1312 			if (compiler.Settings.LoadDefaultReferences) {
1313 				foreach (string r in GetDefaultReferences ()) {
1314 					a = LoadAssemblyFile (r, true);
1315 					if (a == null)
1316 						continue;
1317 
1318 					var key = Tuple.Create (module.GlobalRootNamespace, a);
1319 					if (loaded.Contains (key))
1320 						continue;
1321 
1322 					loaded.Add (key);
1323 				}
1324 			}
1325 
1326 			compiler.TimeReporter.Stop (TimeReporter.TimerType.ReferencesLoading);
1327 		}
1328 	}
1329 }
1330