602 lines
16 KiB
C#
602 lines
16 KiB
C#
|
//
|
||
|
// ModuleDefinition.cs
|
||
|
//
|
||
|
// Author:
|
||
|
// Jb Evain (jbevain@gmail.com)
|
||
|
//
|
||
|
// (C) 2005 Jb Evain
|
||
|
//
|
||
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||
|
// a copy of this software and associated documentation files (the
|
||
|
// "Software"), to deal in the Software without restriction, including
|
||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||
|
// permit persons to whom the Software is furnished to do so, subject to
|
||
|
// the following conditions:
|
||
|
//
|
||
|
// The above copyright notice and this permission notice shall be
|
||
|
// included in all copies or substantial portions of the Software.
|
||
|
//
|
||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
//
|
||
|
|
||
|
namespace Mono.Cecil {
|
||
|
|
||
|
using System;
|
||
|
using SR = System.Reflection;
|
||
|
using SS = System.Security;
|
||
|
using SSP = System.Security.Permissions;
|
||
|
using System.Text;
|
||
|
|
||
|
using Mono.Cecil.Cil;
|
||
|
using Mono.Cecil.Binary;
|
||
|
using Mono.Cecil.Metadata;
|
||
|
|
||
|
internal sealed class ModuleDefinition : ModuleReference, ICustomAttributeProvider, IMetadataScope,
|
||
|
IReflectionStructureVisitable, IReflectionVisitable {
|
||
|
|
||
|
Guid m_mvid;
|
||
|
bool m_main;
|
||
|
bool m_manifestOnly;
|
||
|
|
||
|
AssemblyNameReferenceCollection m_asmRefs;
|
||
|
ModuleReferenceCollection m_modRefs;
|
||
|
ResourceCollection m_res;
|
||
|
TypeDefinitionCollection m_types;
|
||
|
TypeReferenceCollection m_refs;
|
||
|
ExternTypeCollection m_externs;
|
||
|
MemberReferenceCollection m_members;
|
||
|
CustomAttributeCollection m_customAttrs;
|
||
|
|
||
|
AssemblyDefinition m_asm;
|
||
|
Image m_image;
|
||
|
|
||
|
ImageReader m_imgReader;
|
||
|
ReflectionController m_controller;
|
||
|
MetadataResolver m_resolver;
|
||
|
SecurityDeclarationReader m_secReader;
|
||
|
|
||
|
public Guid Mvid {
|
||
|
get { return m_mvid; }
|
||
|
set { m_mvid = value; }
|
||
|
}
|
||
|
|
||
|
public bool Main {
|
||
|
get { return m_main; }
|
||
|
set { m_main = value; }
|
||
|
}
|
||
|
|
||
|
public AssemblyNameReferenceCollection AssemblyReferences {
|
||
|
get { return m_asmRefs; }
|
||
|
}
|
||
|
|
||
|
public ModuleReferenceCollection ModuleReferences {
|
||
|
get { return m_modRefs; }
|
||
|
}
|
||
|
|
||
|
public ResourceCollection Resources {
|
||
|
get { return m_res; }
|
||
|
}
|
||
|
|
||
|
public TypeDefinitionCollection Types {
|
||
|
get { return m_types; }
|
||
|
}
|
||
|
|
||
|
public TypeReferenceCollection TypeReferences {
|
||
|
get { return m_refs; }
|
||
|
}
|
||
|
|
||
|
public MemberReferenceCollection MemberReferences {
|
||
|
get { return m_members; }
|
||
|
}
|
||
|
|
||
|
public ExternTypeCollection ExternTypes {
|
||
|
get {
|
||
|
if (m_externs == null)
|
||
|
m_externs = new ExternTypeCollection (this);
|
||
|
|
||
|
return m_externs;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool HasCustomAttributes {
|
||
|
get { return (m_customAttrs == null) ? false : (m_customAttrs.Count > 0); }
|
||
|
}
|
||
|
|
||
|
public CustomAttributeCollection CustomAttributes {
|
||
|
get {
|
||
|
if (m_customAttrs == null)
|
||
|
m_customAttrs = new CustomAttributeCollection (this);
|
||
|
|
||
|
return m_customAttrs;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public AssemblyDefinition Assembly {
|
||
|
get { return m_asm; }
|
||
|
}
|
||
|
|
||
|
internal ReflectionController Controller {
|
||
|
get { return m_controller; }
|
||
|
}
|
||
|
|
||
|
internal MetadataResolver Resolver {
|
||
|
get { return m_resolver; }
|
||
|
}
|
||
|
|
||
|
internal ImageReader ImageReader {
|
||
|
get { return m_imgReader; }
|
||
|
}
|
||
|
|
||
|
public Image Image {
|
||
|
get { return m_image; }
|
||
|
set {
|
||
|
m_image = value;
|
||
|
m_secReader = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public ModuleDefinition (string name, AssemblyDefinition asm) :
|
||
|
this (name, asm, null, false)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public ModuleDefinition (string name, AssemblyDefinition asm, bool main) :
|
||
|
this (name, asm, null, main)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
internal ModuleDefinition (string name, AssemblyDefinition asm, StructureReader reader, bool main) : base (name)
|
||
|
{
|
||
|
if (asm == null)
|
||
|
throw new ArgumentNullException ("asm");
|
||
|
if (name == null || name.Length == 0)
|
||
|
throw new ArgumentNullException ("name");
|
||
|
|
||
|
m_asm = asm;
|
||
|
m_main = main;
|
||
|
#if !CF_1_0
|
||
|
m_mvid = Guid.NewGuid ();
|
||
|
#endif
|
||
|
if (reader != null) {
|
||
|
m_image = reader.Image;
|
||
|
m_imgReader = reader.ImageReader;
|
||
|
m_manifestOnly = reader.ManifestOnly;
|
||
|
} else
|
||
|
m_image = Image.CreateImage ();
|
||
|
|
||
|
m_modRefs = new ModuleReferenceCollection (this);
|
||
|
m_asmRefs = new AssemblyNameReferenceCollection (this);
|
||
|
m_res = new ResourceCollection (this);
|
||
|
m_types = new TypeDefinitionCollection (this);
|
||
|
m_refs = new TypeReferenceCollection (this);
|
||
|
m_members = new MemberReferenceCollection (this);
|
||
|
|
||
|
m_controller = new ReflectionController (this);
|
||
|
m_resolver = new MetadataResolver (asm);
|
||
|
}
|
||
|
|
||
|
public IMetadataTokenProvider LookupByToken (MetadataToken token)
|
||
|
{
|
||
|
return m_controller.Reader.LookupByToken (token);
|
||
|
}
|
||
|
|
||
|
public IMetadataTokenProvider LookupByToken (TokenType table, int rid)
|
||
|
{
|
||
|
return LookupByToken (new MetadataToken (table, (uint) rid));
|
||
|
}
|
||
|
|
||
|
void CheckContext (TypeDefinition context)
|
||
|
{
|
||
|
if (context.Module != this)
|
||
|
throw new ArgumentException ("The context parameter does not belongs to this module");
|
||
|
|
||
|
CheckGenericParameterProvider (context);
|
||
|
}
|
||
|
|
||
|
void CheckContext (MethodDefinition context)
|
||
|
{
|
||
|
CheckGenericParameterProvider (context);
|
||
|
}
|
||
|
|
||
|
static void CheckGenericParameterProvider (IGenericParameterProvider context)
|
||
|
{
|
||
|
if (context == null)
|
||
|
throw new ArgumentNullException ("context");
|
||
|
if (context.GenericParameters.Count == 0)
|
||
|
throw new ArgumentException ("The context parameter is not a generic type");
|
||
|
}
|
||
|
|
||
|
ImportContext GetContext ()
|
||
|
{
|
||
|
return new ImportContext (m_controller.Importer);
|
||
|
}
|
||
|
|
||
|
static ImportContext GetContext (IImporter importer)
|
||
|
{
|
||
|
return new ImportContext (importer);
|
||
|
}
|
||
|
|
||
|
ImportContext GetContext (TypeDefinition context)
|
||
|
{
|
||
|
return new ImportContext (m_controller.Importer, context);
|
||
|
}
|
||
|
|
||
|
ImportContext GetContext (MethodDefinition context)
|
||
|
{
|
||
|
return new ImportContext (m_controller.Importer, context);
|
||
|
}
|
||
|
|
||
|
static ImportContext GetContext (IImporter importer, TypeDefinition context)
|
||
|
{
|
||
|
return new ImportContext (importer, context);
|
||
|
}
|
||
|
|
||
|
public TypeReference Import (Type type)
|
||
|
{
|
||
|
if (type == null)
|
||
|
throw new ArgumentNullException ("type");
|
||
|
|
||
|
return m_controller.Helper.ImportSystemType (type, GetContext ());
|
||
|
}
|
||
|
|
||
|
public TypeReference Import (Type type, TypeDefinition context)
|
||
|
{
|
||
|
if (type == null)
|
||
|
throw new ArgumentNullException ("type");
|
||
|
CheckContext (context);
|
||
|
|
||
|
return m_controller.Helper.ImportSystemType (type, GetContext (context));
|
||
|
}
|
||
|
|
||
|
public TypeReference Import (Type type, MethodDefinition context)
|
||
|
{
|
||
|
if (type == null)
|
||
|
throw new ArgumentNullException ("type");
|
||
|
CheckContext (context);
|
||
|
|
||
|
return m_controller.Helper.ImportSystemType (type, GetContext (context));
|
||
|
}
|
||
|
|
||
|
public MethodReference Import (SR.MethodBase meth)
|
||
|
{
|
||
|
if (meth == null)
|
||
|
throw new ArgumentNullException ("meth");
|
||
|
|
||
|
if (meth is SR.ConstructorInfo)
|
||
|
return m_controller.Helper.ImportConstructorInfo (
|
||
|
meth as SR.ConstructorInfo, GetContext ());
|
||
|
else
|
||
|
return m_controller.Helper.ImportMethodInfo (
|
||
|
meth as SR.MethodInfo, GetContext ());
|
||
|
}
|
||
|
|
||
|
public MethodReference Import (SR.MethodBase meth, TypeDefinition context)
|
||
|
{
|
||
|
if (meth == null)
|
||
|
throw new ArgumentNullException ("meth");
|
||
|
CheckContext (context);
|
||
|
|
||
|
ImportContext import_context = GetContext (context);
|
||
|
|
||
|
if (meth is SR.ConstructorInfo)
|
||
|
return m_controller.Helper.ImportConstructorInfo (
|
||
|
meth as SR.ConstructorInfo, import_context);
|
||
|
else
|
||
|
return m_controller.Helper.ImportMethodInfo (
|
||
|
meth as SR.MethodInfo, import_context);
|
||
|
}
|
||
|
|
||
|
public FieldReference Import (SR.FieldInfo field)
|
||
|
{
|
||
|
if (field == null)
|
||
|
throw new ArgumentNullException ("field");
|
||
|
|
||
|
return m_controller.Helper.ImportFieldInfo (field, GetContext ());
|
||
|
}
|
||
|
|
||
|
public FieldReference Import (SR.FieldInfo field, TypeDefinition context)
|
||
|
{
|
||
|
if (field == null)
|
||
|
throw new ArgumentNullException ("field");
|
||
|
CheckContext (context);
|
||
|
|
||
|
return m_controller.Helper.ImportFieldInfo (field, GetContext (context));
|
||
|
}
|
||
|
|
||
|
public FieldReference Import (SR.FieldInfo field, MethodDefinition context)
|
||
|
{
|
||
|
if (field == null)
|
||
|
throw new ArgumentNullException ("field");
|
||
|
CheckContext (context);
|
||
|
|
||
|
return m_controller.Helper.ImportFieldInfo (field, GetContext (context));
|
||
|
}
|
||
|
|
||
|
public TypeReference Import (TypeReference type)
|
||
|
{
|
||
|
if (type == null)
|
||
|
throw new ArgumentNullException ("type");
|
||
|
|
||
|
return m_controller.Importer.ImportTypeReference (type, GetContext ());
|
||
|
}
|
||
|
|
||
|
public TypeReference Import (TypeReference type, TypeDefinition context)
|
||
|
{
|
||
|
if (type == null)
|
||
|
throw new ArgumentNullException ("type");
|
||
|
CheckContext (context);
|
||
|
|
||
|
return m_controller.Importer.ImportTypeReference (type, GetContext (context));
|
||
|
}
|
||
|
|
||
|
public TypeReference Import (TypeReference type, MethodDefinition context)
|
||
|
{
|
||
|
if (type == null)
|
||
|
throw new ArgumentNullException ("type");
|
||
|
CheckContext (context);
|
||
|
|
||
|
return m_controller.Importer.ImportTypeReference (type, GetContext (context));
|
||
|
}
|
||
|
|
||
|
public MethodReference Import (MethodReference meth)
|
||
|
{
|
||
|
if (meth == null)
|
||
|
throw new ArgumentNullException ("meth");
|
||
|
|
||
|
return m_controller.Importer.ImportMethodReference (meth, GetContext ());
|
||
|
}
|
||
|
|
||
|
public MethodReference Import (MethodReference meth, TypeDefinition context)
|
||
|
{
|
||
|
if (meth == null)
|
||
|
throw new ArgumentNullException ("meth");
|
||
|
CheckContext (context);
|
||
|
|
||
|
return m_controller.Importer.ImportMethodReference (meth, GetContext (context));
|
||
|
}
|
||
|
|
||
|
public MethodReference Import (MethodReference meth, MethodDefinition context)
|
||
|
{
|
||
|
if (meth == null)
|
||
|
throw new ArgumentNullException ("meth");
|
||
|
CheckContext (context);
|
||
|
|
||
|
return m_controller.Importer.ImportMethodReference (meth, GetContext (context));
|
||
|
}
|
||
|
|
||
|
public FieldReference Import (FieldReference field)
|
||
|
{
|
||
|
if (field == null)
|
||
|
throw new ArgumentNullException ("field");
|
||
|
|
||
|
return m_controller.Importer.ImportFieldReference (field, GetContext ());
|
||
|
}
|
||
|
|
||
|
public FieldReference Import (FieldReference field, TypeDefinition context)
|
||
|
{
|
||
|
if (field == null)
|
||
|
throw new ArgumentNullException ("field");
|
||
|
CheckContext (context);
|
||
|
|
||
|
return m_controller.Importer.ImportFieldReference (field, GetContext (context));
|
||
|
}
|
||
|
|
||
|
public FieldReference Import (FieldReference field, MethodDefinition context)
|
||
|
{
|
||
|
if (field == null)
|
||
|
throw new ArgumentNullException ("field");
|
||
|
CheckContext (context);
|
||
|
|
||
|
return m_controller.Importer.ImportFieldReference (field, GetContext (context));
|
||
|
}
|
||
|
|
||
|
static FieldDefinition ImportFieldDefinition (FieldDefinition field, ImportContext context)
|
||
|
{
|
||
|
return FieldDefinition.Clone (field, context);
|
||
|
}
|
||
|
|
||
|
static MethodDefinition ImportMethodDefinition (MethodDefinition meth, ImportContext context)
|
||
|
{
|
||
|
return MethodDefinition.Clone (meth, context);
|
||
|
}
|
||
|
|
||
|
static TypeDefinition ImportTypeDefinition (TypeDefinition type, ImportContext context)
|
||
|
{
|
||
|
return TypeDefinition.Clone (type, context);
|
||
|
}
|
||
|
|
||
|
public TypeDefinition Inject (TypeDefinition type)
|
||
|
{
|
||
|
return Inject (type, m_controller.Importer);
|
||
|
}
|
||
|
|
||
|
public TypeDefinition Inject (TypeDefinition type, IImporter importer)
|
||
|
{
|
||
|
if (type == null)
|
||
|
throw new ArgumentNullException ("type");
|
||
|
if (importer == null)
|
||
|
throw new ArgumentNullException ("importer");
|
||
|
|
||
|
TypeDefinition definition = ImportTypeDefinition (type, GetContext (importer));
|
||
|
this.Types.Add (definition);
|
||
|
return definition;
|
||
|
}
|
||
|
|
||
|
public TypeDefinition Inject (TypeDefinition type, TypeDefinition context)
|
||
|
{
|
||
|
return Inject (type, context, m_controller.Importer);
|
||
|
}
|
||
|
|
||
|
public TypeDefinition Inject (TypeDefinition type, TypeDefinition context, IImporter importer)
|
||
|
{
|
||
|
Check (type, context, importer);
|
||
|
|
||
|
TypeDefinition definition = ImportTypeDefinition (type, GetContext (importer, context));
|
||
|
context.NestedTypes.Add (definition);
|
||
|
return definition;
|
||
|
}
|
||
|
|
||
|
public MethodDefinition Inject (MethodDefinition meth, TypeDefinition context)
|
||
|
{
|
||
|
return Inject (meth, context, m_controller.Importer);
|
||
|
}
|
||
|
|
||
|
void Check (IMemberDefinition definition, TypeDefinition context, IImporter importer)
|
||
|
{
|
||
|
if (definition == null)
|
||
|
throw new ArgumentNullException ("definition");
|
||
|
if (context == null)
|
||
|
throw new ArgumentNullException ("context");
|
||
|
if (importer == null)
|
||
|
throw new ArgumentNullException ("importer");
|
||
|
if (context.Module != this)
|
||
|
throw new ArgumentException ("The context parameter does not belongs to this module");
|
||
|
}
|
||
|
|
||
|
public MethodDefinition Inject (MethodDefinition meth, TypeDefinition context, IImporter importer)
|
||
|
{
|
||
|
Check (meth, context, importer);
|
||
|
|
||
|
MethodDefinition definition = ImportMethodDefinition (meth, GetContext (importer, context));
|
||
|
context.Methods.Add (definition);
|
||
|
return definition;
|
||
|
}
|
||
|
|
||
|
public FieldDefinition Inject (FieldDefinition field, TypeDefinition context)
|
||
|
{
|
||
|
return Inject (field, context, m_controller.Importer);
|
||
|
}
|
||
|
|
||
|
public FieldDefinition Inject (FieldDefinition field, TypeDefinition context, IImporter importer)
|
||
|
{
|
||
|
Check (field, context, importer);
|
||
|
|
||
|
FieldDefinition definition = ImportFieldDefinition (field, GetContext (importer, context));
|
||
|
context.Fields.Add (definition);
|
||
|
return definition;
|
||
|
}
|
||
|
|
||
|
public void FullLoad ()
|
||
|
{
|
||
|
if (m_manifestOnly)
|
||
|
m_controller.Reader.VisitModuleDefinition (this);
|
||
|
|
||
|
foreach (TypeDefinition type in this.Types) {
|
||
|
foreach (MethodDefinition meth in type.Methods)
|
||
|
meth.LoadBody ();
|
||
|
foreach (MethodDefinition ctor in type.Constructors)
|
||
|
ctor.LoadBody ();
|
||
|
}
|
||
|
|
||
|
if (m_controller.Reader.SymbolReader == null)
|
||
|
return;
|
||
|
|
||
|
m_controller.Reader.SymbolReader.Dispose ();
|
||
|
m_controller.Reader.SymbolReader = null;
|
||
|
}
|
||
|
|
||
|
public void LoadSymbols ()
|
||
|
{
|
||
|
m_controller.Reader.SymbolReader = SymbolStoreHelper.GetReader (this);
|
||
|
}
|
||
|
|
||
|
public void LoadSymbols (ISymbolReader reader)
|
||
|
{
|
||
|
m_controller.Reader.SymbolReader = reader;
|
||
|
}
|
||
|
|
||
|
public void SaveSymbols ()
|
||
|
{
|
||
|
m_controller.Writer.SaveSymbols = true;
|
||
|
}
|
||
|
|
||
|
public void SaveSymbols (ISymbolWriter writer)
|
||
|
{
|
||
|
SaveSymbols ();
|
||
|
m_controller.Writer.SymbolWriter = writer;
|
||
|
}
|
||
|
|
||
|
public void SaveSymbols (string outputDirectory)
|
||
|
{
|
||
|
SaveSymbols ();
|
||
|
m_controller.Writer.OutputFile = outputDirectory;
|
||
|
}
|
||
|
|
||
|
public void SaveSymbols (string outputDirectory, ISymbolWriter writer)
|
||
|
{
|
||
|
SaveSymbols (outputDirectory);
|
||
|
m_controller.Writer.SymbolWriter = writer;
|
||
|
}
|
||
|
|
||
|
public byte [] GetAsByteArray (CustomAttribute ca)
|
||
|
{
|
||
|
CustomAttribute customAttr = ca;
|
||
|
if (!ca.Resolved)
|
||
|
if (customAttr.Blob != null)
|
||
|
return customAttr.Blob;
|
||
|
else
|
||
|
return new byte [0];
|
||
|
|
||
|
return m_controller.Writer.SignatureWriter.CompressCustomAttribute (
|
||
|
ReflectionWriter.GetCustomAttributeSig (ca), ca.Constructor);
|
||
|
}
|
||
|
|
||
|
public byte [] GetAsByteArray (SecurityDeclaration dec)
|
||
|
{
|
||
|
// TODO - add support for 2.0 format
|
||
|
// note: the 1.x format is still supported in 2.0 so this isn't an immediate problem
|
||
|
if (!dec.Resolved)
|
||
|
return dec.Blob;
|
||
|
|
||
|
#if !CF_1_0 && !CF_2_0
|
||
|
if (dec.PermissionSet != null)
|
||
|
return Encoding.Unicode.GetBytes (dec.PermissionSet.ToXml ().ToString ());
|
||
|
#endif
|
||
|
|
||
|
return new byte [0];
|
||
|
}
|
||
|
|
||
|
public CustomAttribute FromByteArray (MethodReference ctor, byte [] data)
|
||
|
{
|
||
|
return m_controller.Reader.GetCustomAttribute (ctor, data);
|
||
|
}
|
||
|
|
||
|
public SecurityDeclaration FromByteArray (SecurityAction action, byte [] declaration)
|
||
|
{
|
||
|
if (m_secReader == null)
|
||
|
m_secReader = new SecurityDeclarationReader (Image.MetadataRoot, m_controller.Reader);
|
||
|
return m_secReader.FromByteArray (action, declaration);
|
||
|
}
|
||
|
|
||
|
public override void Accept (IReflectionStructureVisitor visitor)
|
||
|
{
|
||
|
visitor.VisitModuleDefinition (this);
|
||
|
|
||
|
this.AssemblyReferences.Accept (visitor);
|
||
|
this.ModuleReferences.Accept (visitor);
|
||
|
this.Resources.Accept (visitor);
|
||
|
}
|
||
|
|
||
|
public void Accept (IReflectionVisitor visitor)
|
||
|
{
|
||
|
visitor.VisitModuleDefinition (this);
|
||
|
|
||
|
this.Types.Accept (visitor);
|
||
|
this.TypeReferences.Accept (visitor);
|
||
|
}
|
||
|
|
||
|
public override string ToString ()
|
||
|
{
|
||
|
string s = (m_main ? "(main), Mvid=" : "Mvid=");
|
||
|
return s + m_mvid;
|
||
|
}
|
||
|
}
|
||
|
}
|