using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+
+using Mono.Security.Cryptography;
namespace Mono.CSharp {
//
static public void Init (string name, string output, bool want_debugging_support)
{
- AssemblyName an;
-
FileName = output;
- an = new AssemblyName ();
- an.Name = Path.GetFileNameWithoutExtension (name);
+ AssemblyName an = Assembly.GetAssemblyName (name, output);
+
+ if (an.KeyPair != null) {
+ // If we are going to strong name our assembly make
+ // sure all its refs are strong named
+ foreach (Assembly a in TypeManager.GetAssemblies ()) {
+ AssemblyName ref_name = a.GetName ();
+ byte [] b = ref_name.GetPublicKeyToken ();
+ if (b == null || b.Length == 0) {
+ Report.Warning (1577, "Assembly generation failed " +
+ "-- Referenced assembly '" +
+ ref_name.Name +
+ "' does not have a strong name.");
+ //Environment.Exit (1);
+ }
+ }
+ }
current_domain = AppDomain.CurrentDomain;
- Assembly.Builder = current_domain.DefineDynamicAssembly (
- an, AssemblyBuilderAccess.Save, Dirname (name));
+
+ try {
+ Assembly.Builder = current_domain.DefineDynamicAssembly (an,
+ AssemblyBuilderAccess.Save, Dirname (name));
+ }
+ catch (ArgumentException) {
+ // specified key may not be exportable outside it's container
+ if (RootContext.StrongNameKeyContainer != null) {
+ Report.Error (1548, "Could not access the key inside the container `" +
+ RootContext.StrongNameKeyContainer + "'.");
+ Environment.Exit (1);
+ }
+ throw;
+ }
+ catch (CryptographicException) {
+ if ((RootContext.StrongNameKeyContainer != null) || (RootContext.StrongNameKeyFile != null)) {
+ Report.Error (1548, "Could not use the specified key to strongname the assembly.");
+ Environment.Exit (1);
+ }
+ throw;
+ }
//
// Pass a path-less name to DefineDynamicModule. Wonder how
{
try {
Assembly.Builder.Save (Basename (name));
- } catch (System.IO.IOException io){
+ }
+ catch (COMException) {
+ if ((RootContext.StrongNameKeyFile == null) || (!RootContext.StrongNameDelaySign))
+ throw;
+
+ // FIXME: it seems Microsoft AssemblyBuilder doesn't like to delay sign assemblies
+ Report.Error (1548, "Couldn't delay-sign the assembly with the '" +
+ RootContext.StrongNameKeyFile +
+ "', Use MCS with the Mono runtime or CSC to compile this assembly.");
+ }
+ catch (System.IO.IOException io) {
Report.Error (16, "Could not write to file `"+name+"', cause: " + io.Message);
}
}
reachability.IsUnreachable)
unreachable = true;
}
+#if FIXME
} catch (Exception e) {
Console.WriteLine ("Exception caught by the compiler while compiling:");
Console.WriteLine (" Block that caused the problem begin at: " + loc);
Console.WriteLine (Report.FriendlyStackTrace (e));
Environment.Exit (1);
+#else
+ } finally {
+#endif
}
}
//
public void EmitThis ()
{
- ig.Emit (OpCodes.Ldarg_0);
-
- if (!IsStatic){
- if (InIterator)
- ig.Emit (OpCodes.Ldfld, IteratorHandler.Current.this_field);
- else
- throw new Exception ("EmitThis for an unknown state");
- }
+ if (InIterator){
+ ig.Emit (OpCodes.Ldarg_0);
+ if (!IsStatic){
+ FieldBuilder this_field = IteratorHandler.Current.this_field;
+ if (TypeManager.IsValueType (this_field.FieldType))
+ ig.Emit (OpCodes.Ldflda, this_field);
+ else
+ ig.Emit (OpCodes.Ldfld, this_field);
+ }
+ } else
+ ig.Emit (OpCodes.Ldarg_0);
}
public Expression GetThis (Location loc)
}
- public abstract class CommonAssemblyModulClass: IAttributeSupport {
- Hashtable m_attributes;
+ public abstract class CommonAssemblyModulClass: Attributable {
+ static string[] attribute_targets = new string [] { "assembly", "module" };
- protected CommonAssemblyModulClass ()
+ protected CommonAssemblyModulClass ():
+ base (null)
{
- m_attributes = new Hashtable ();
}
- //
- // Adds a global attribute that was declared in `container',
- // the attribute is in `attr', and it was defined at `loc'
- //
- public void AddAttribute (TypeContainer container, AttributeSection attr)
+ public void AddAttributes (ArrayList attrs)
{
- NamespaceEntry ns = container.NamespaceEntry;
- Attributes a = (Attributes) m_attributes [ns];
-
- if (a == null) {
- m_attributes [ns] = new Attributes (attr);
+ if (OptAttributes == null) {
+ OptAttributes = new Attributes (attrs);
return;
}
-
- a.AddAttributeSection (attr);
+ OptAttributes.AddAttributes (attrs);
+ OptAttributes.CheckTargets (ValidAttributeTargets);
}
- public virtual void Emit ()
+ public virtual void Emit (TypeContainer tc)
{
- if (m_attributes.Count < 1)
+ if (OptAttributes == null)
return;
- TypeContainer dummy = new TypeContainer ();
- EmitContext temp_ec = new EmitContext (dummy, Mono.CSharp.Location.Null, null, null, 0, false);
-
- foreach (DictionaryEntry de in m_attributes)
- {
- NamespaceEntry ns = (NamespaceEntry) de.Key;
- Attributes attrs = (Attributes) de.Value;
-
- dummy.NamespaceEntry = ns;
- Attribute.ApplyAttributes (temp_ec, null, this, attrs);
+ EmitContext ec = new EmitContext (tc, Mono.CSharp.Location.Null, null, null, 0, false);
+ OptAttributes.Emit (ec, this);
+ }
+
+ protected Attribute GetClsCompliantAttribute ()
+ {
+ if (OptAttributes == null)
+ return null;
+
+ EmitContext temp_ec = new EmitContext (new TypeContainer (), Mono.CSharp.Location.Null, null, null, 0, false);
+ Attribute a = OptAttributes.Search (TypeManager.cls_compliant_attribute_type, temp_ec);
+ if (a != null) {
+ a.Resolve (temp_ec);
}
+ return a;
}
-
- #region IAttributeSupport Members
- public abstract void SetCustomAttribute(CustomAttributeBuilder customBuilder);
- #endregion
+ protected override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
}
-
public class AssemblyClass: CommonAssemblyModulClass {
// TODO: make it private and move all builder based methods here
public AssemblyBuilder Builder;
- bool m_is_cls_compliant;
+ bool is_cls_compliant;
public AssemblyClass (): base ()
{
- m_is_cls_compliant = false;
+ is_cls_compliant = false;
}
public bool IsClsCompliant {
get {
- return m_is_cls_compliant;
+ return is_cls_compliant;
+ }
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Assembly;
+ }
+ }
+
+ public override bool IsClsCompliaceRequired(DeclSpace ds)
+ {
+ return is_cls_compliant;
+ }
+
+ public void ResolveClsCompliance ()
+ {
+ Attribute a = GetClsCompliantAttribute ();
+ if (a == null)
+ return;
+
+ is_cls_compliant = a.GetClsCompliantAttributeValue (null);
+ }
+
+ public AssemblyName GetAssemblyName (string name, string output)
+ {
+ if (OptAttributes != null) {
+ foreach (Attribute a in OptAttributes.Attrs) {
+ if (a.Target != "assembly")
+ continue;
+ // TODO: This code is buggy: comparing Attribute name without resolving it is wrong.
+ // However, this is invoked by CodeGen.Init, at which time none of the namespaces
+ // are loaded yet.
+ switch (a.Name) {
+ case "AssemblyKeyFile":
+ case "AssemblyKeyFileAttribute":
+ case "System.Reflection.AssemblyKeyFileAttribute":
+ if (RootContext.StrongNameKeyFile != null) {
+ Report.Warning (1616, "Compiler option -keyfile overrides " +
+ "AssemblyKeyFileAttribute");
+ }
+ else {
+ string value = a.GetString ();
+ if (value != String.Empty)
+ RootContext.StrongNameKeyFile = value;
+ }
+ break;
+ case "AssemblyKeyName":
+ case "AssemblyKeyNameAttribute":
+ case "System.Reflection.AssemblyKeyNameAttribute":
+ if (RootContext.StrongNameKeyContainer != null) {
+ Report.Warning (1616, "Compiler option -keycontainer overrides " +
+ "AssemblyKeyNameAttribute");
+ }
+ else {
+ string value = a.GetString ();
+ if (value != String.Empty)
+ RootContext.StrongNameKeyContainer = value;
+ }
+ break;
+ case "AssemblyDelaySign":
+ case "AssemblyDelaySignAttribute":
+ case "System.Reflection.AssemblyDelaySignAttribute":
+ RootContext.StrongNameDelaySign = a.GetBoolean ();
+ break;
+ }
+ }
+ }
+
+ AssemblyName an = new AssemblyName ();
+ an.Name = Path.GetFileNameWithoutExtension (name);
+
+ // note: delay doesn't apply when using a key container
+ if (RootContext.StrongNameKeyContainer != null) {
+ an.KeyPair = new StrongNameKeyPair (RootContext.StrongNameKeyContainer);
+ return an;
+ }
+
+ // strongname is optional
+ if (RootContext.StrongNameKeyFile == null)
+ return an;
+
+ string AssemblyDir = Path.GetDirectoryName (output);
+
+ // the StrongName key file may be relative to (a) the compiled
+ // file or (b) to the output assembly. See bugzilla #55320
+ // http://bugzilla.ximian.com/show_bug.cgi?id=55320
+
+ // (a) relative to the compiled file
+ string filename = Path.GetFullPath (RootContext.StrongNameKeyFile);
+ bool exist = File.Exists (filename);
+ if ((!exist) && (AssemblyDir != null) && (AssemblyDir != String.Empty)) {
+ // (b) relative to the outputed assembly
+ filename = Path.GetFullPath (Path.Combine (AssemblyDir, RootContext.StrongNameKeyFile));
+ exist = File.Exists (filename);
}
+
+ if (exist) {
+ using (FileStream fs = new FileStream (filename, FileMode.Open, FileAccess.Read)) {
+ byte[] snkeypair = new byte [fs.Length];
+ fs.Read (snkeypair, 0, snkeypair.Length);
+
+ if (RootContext.StrongNameDelaySign) {
+ // delayed signing - DO NOT include private key
+ try {
+ // check for possible ECMA key
+ if (snkeypair.Length == 16) {
+ // will be rejected if not "the" ECMA key
+ an.KeyPair = new StrongNameKeyPair (snkeypair);
+ }
+ else {
+ // take it, with or without, a private key
+ RSA rsa = CryptoConvert.FromCapiKeyBlob (snkeypair);
+ // and make sure we only feed the public part to Sys.Ref
+ byte[] publickey = CryptoConvert.ToCapiPublicKeyBlob (rsa);
+ an.KeyPair = new StrongNameKeyPair (publickey);
+ }
+ }
+ catch (Exception) {
+ Report.Error (1548, "Could not strongname the assembly. File `" +
+ RootContext.StrongNameKeyFile + "' incorrectly encoded.");
+ Environment.Exit (1);
+ }
+ }
+ else {
+ // no delay so we make sure we have the private key
+ try {
+ CryptoConvert.FromCapiPrivateKeyBlob (snkeypair);
+ an.KeyPair = new StrongNameKeyPair (snkeypair);
+ }
+ catch (CryptographicException) {
+ if (snkeypair.Length == 16) {
+ // error # is different for ECMA key
+ Report.Error (1606, "Could not strongname the assembly. " +
+ "ECMA key can only be used to delay-sign assemblies");
+ }
+ else {
+ Report.Error (1548, "Could not strongname the assembly. File `" +
+ RootContext.StrongNameKeyFile +
+ "' doesn't have a private key.");
+ }
+ Environment.Exit (1);
+ }
+ }
+ }
+ }
+ else {
+ Report.Error (1548, "Could not strongname the assembly. File `" +
+ RootContext.StrongNameKeyFile + "' not found.");
+ Environment.Exit (1);
+ }
+ return an;
}
- public override void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder)
{
Builder.SetCustomAttribute (customBuilder);
}
public class ModuleClass: CommonAssemblyModulClass {
// TODO: make it private and move all builder based methods here
public ModuleBuilder Builder;
-
bool m_module_is_unsafe;
public ModuleClass (bool is_unsafe)
m_module_is_unsafe = is_unsafe;
}
- public override void Emit ()
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Module;
+ }
+ }
+
+ public override bool IsClsCompliaceRequired(DeclSpace ds)
{
- base.Emit ();
+ return CodeGen.Assembly.IsClsCompliant;
+ }
+
+ public override void Emit (TypeContainer tc)
+ {
+ base.Emit (tc);
if (!m_module_is_unsafe)
return;
return;
}
- SetCustomAttribute (new CustomAttributeBuilder (TypeManager.unverifiable_code_ctor, new object [0]));
+ ApplyAttributeBuilder (null, new CustomAttributeBuilder (TypeManager.unverifiable_code_ctor, new object [0]));
}
- public override void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder)
{
+ if (a != null && a.Type == TypeManager.cls_compliant_attribute_type) {
+ Report.Warning_T (3012, a.Location);
+ return;
+ }
+
Builder.SetCustomAttribute (customBuilder);
}
}