Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,241 @@
//
// Annotations.cs
//
// Author:
// Jb Evain (jbevain@novell.com)
//
// (C) 2007 Novell, Inc.
//
// 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.
//
using System;
using System.Collections;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace Mono.Linker {
public class AnnotationStore {
readonly Dictionary<AssemblyDefinition, AssemblyAction> assembly_actions = new Dictionary<AssemblyDefinition, AssemblyAction> ();
readonly Dictionary<MethodDefinition, MethodAction> method_actions = new Dictionary<MethodDefinition, MethodAction> ();
readonly HashSet<IMetadataTokenProvider> marked = new HashSet<IMetadataTokenProvider> ();
readonly HashSet<IMetadataTokenProvider> processed = new HashSet<IMetadataTokenProvider> ();
readonly Dictionary<TypeDefinition, TypePreserve> preserved_types = new Dictionary<TypeDefinition, TypePreserve> ();
readonly Dictionary<IMemberDefinition, List<MethodDefinition>> preserved_methods = new Dictionary<IMemberDefinition, List<MethodDefinition>> ();
readonly HashSet<IMetadataTokenProvider> public_api = new HashSet<IMetadataTokenProvider> ();
readonly Dictionary<MethodDefinition, List<MethodDefinition>> override_methods = new Dictionary<MethodDefinition, List<MethodDefinition>> ();
readonly Dictionary<MethodDefinition, List<MethodDefinition>> base_methods = new Dictionary<MethodDefinition, List<MethodDefinition>> ();
readonly Dictionary<AssemblyDefinition, ISymbolReader> symbol_readers = new Dictionary<AssemblyDefinition, ISymbolReader> ();
readonly Dictionary<object, Dictionary<IMetadataTokenProvider, object>> custom_annotations = new Dictionary<object, Dictionary<IMetadataTokenProvider, object>> ();
public AssemblyAction GetAction (AssemblyDefinition assembly)
{
AssemblyAction action;
if (assembly_actions.TryGetValue (assembly, out action))
return action;
throw new NotSupportedException ();
}
public MethodAction GetAction (MethodDefinition method)
{
MethodAction action;
if (method_actions.TryGetValue (method, out action))
return action;
return MethodAction.Nothing;
}
public void SetAction (AssemblyDefinition assembly, AssemblyAction action)
{
assembly_actions [assembly] = action;
}
public bool HasAction (AssemblyDefinition assembly)
{
return assembly_actions.ContainsKey (assembly);
}
public void SetAction (MethodDefinition method, MethodAction action)
{
method_actions [method] = action;
}
public void Mark (IMetadataTokenProvider provider)
{
marked.Add (provider);
}
public bool IsMarked (IMetadataTokenProvider provider)
{
return marked.Contains (provider);
}
public void Processed (IMetadataTokenProvider provider)
{
processed.Add (provider);
}
public bool IsProcessed (IMetadataTokenProvider provider)
{
return processed.Contains (provider);
}
public bool IsPreserved (TypeDefinition type)
{
return preserved_types.ContainsKey (type);
}
public void SetPreserve (TypeDefinition type, TypePreserve preserve)
{
preserved_types [type] = preserve;
}
public TypePreserve GetPreserve (TypeDefinition type)
{
TypePreserve preserve;
if (preserved_types.TryGetValue (type, out preserve))
return preserve;
throw new NotSupportedException ();
}
public void SetPublic (IMetadataTokenProvider provider)
{
public_api.Add (provider);
}
public bool IsPublic (IMetadataTokenProvider provider)
{
return public_api.Contains (provider);
}
public void AddOverride (MethodDefinition @base, MethodDefinition @override)
{
var methods = GetOverrides (@base);
if (methods == null) {
methods = new List<MethodDefinition> ();
override_methods [@base] = methods;
}
methods.Add (@override);
}
public List<MethodDefinition> GetOverrides (MethodDefinition method)
{
List<MethodDefinition> overrides;
if (override_methods.TryGetValue (method, out overrides))
return overrides;
return null;
}
public void AddBaseMethod (MethodDefinition method, MethodDefinition @base)
{
var methods = GetBaseMethods (method);
if (methods == null) {
methods = new List<MethodDefinition> ();
base_methods [method] = methods;
}
methods.Add (@base);
}
public List<MethodDefinition> GetBaseMethods (MethodDefinition method)
{
List<MethodDefinition> bases;
if (base_methods.TryGetValue (method, out bases))
return bases;
return null;
}
public List<MethodDefinition> GetPreservedMethods (TypeDefinition type)
{
return GetPreservedMethods (type as IMemberDefinition);
}
public void AddPreservedMethod (TypeDefinition type, MethodDefinition method)
{
AddPreservedMethod (type as IMemberDefinition, method);
}
public List<MethodDefinition> GetPreservedMethods (MethodDefinition method)
{
return GetPreservedMethods (method as IMemberDefinition);
}
public void AddPreservedMethod (MethodDefinition key, MethodDefinition method)
{
AddPreservedMethod (key as IMemberDefinition, method);
}
List<MethodDefinition> GetPreservedMethods (IMemberDefinition definition)
{
List<MethodDefinition> preserved;
if (preserved_methods.TryGetValue (definition, out preserved))
return preserved;
return null;
}
void AddPreservedMethod (IMemberDefinition definition, MethodDefinition method)
{
var methods = GetPreservedMethods (definition);
if (methods == null) {
methods = new List<MethodDefinition> ();
preserved_methods [definition] = methods;
}
methods.Add (method);
}
public void AddSymbolReader (AssemblyDefinition assembly, ISymbolReader symbolReader)
{
symbol_readers [assembly] = symbolReader;
}
public void CloseSymbolReader (AssemblyDefinition assembly)
{
ISymbolReader symbolReader;
if (!symbol_readers.TryGetValue (assembly, out symbolReader))
return;
symbol_readers.Remove (assembly);
symbolReader.Dispose ();
}
public Dictionary<IMetadataTokenProvider, object> GetCustomAnnotations (object key)
{
Dictionary<IMetadataTokenProvider, object> slots;
if (custom_annotations.TryGetValue (key, out slots))
return slots;
slots = new Dictionary<IMetadataTokenProvider, object> ();
custom_annotations.Add (key, slots);
return slots;
}
}
}

View File

@@ -0,0 +1,46 @@
//
// AssemblyAction.cs
//
// Author:
// Jb Evain (jbevain@gmail.com)
//
// (C) 2006 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.Linker {
public enum AssemblyAction {
// Ignore the assembly
Skip,
// Copy the existing files, assembly and symbols, into the output destination. E.g. .dll and .mdb
// The linker still analyze the assemblies (to know what they require) but does not modify them
Copy,
// Link the assembly
Link,
// Remove the assembly from the output
Delete,
// Save the assembly/symbols in memory without linking it.
// E.g. useful to remove unneeded assembly references (as done in SweepStep),
// resolving [TypeForwardedTo] attributes (like PCL) to their final location
Save
}
}

View File

@@ -0,0 +1,43 @@
//
// AssemblyInfo.cs
//
// Author:
// Jb Evain (jbevain@gmail.com)
//
// (C) 2006 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.
//
using System;
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle ("Mono.Linker")]
[assembly: AssemblyDescription ("Mono CIL Linker")]
[assembly: AssemblyConfiguration ("")]
[assembly: AssemblyProduct ("")]
[assembly: AssemblyCopyright ("(C) 2006, Jb Evain")]
[assembly: AssemblyCulture ("")]
[assembly: CLSCompliant (false)]
[assembly: ComVisible (false)]
[assembly: AssemblyVersion ("0.2.0.0")]

View File

@@ -0,0 +1,71 @@
//
// AssemblyResolver.cs
//
// Author:
// Jb Evain (jbevain@novell.com)
//
// (C) 2007 Novell, Inc.
//
// 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.
//
using System;
using System.Collections;
using System.IO;
using Mono.Cecil;
namespace Mono.Linker {
public class AssemblyResolver : BaseAssemblyResolver {
IDictionary _assemblies;
public IDictionary AssemblyCache {
get { return _assemblies; }
}
public AssemblyResolver ()
: this (new Hashtable ())
{
}
public AssemblyResolver (IDictionary assembly_cache)
{
_assemblies = assembly_cache;
}
public override AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters)
{
AssemblyDefinition asm = (AssemblyDefinition) _assemblies [name.Name];
if (asm == null) {
asm = base.Resolve (name, parameters);
_assemblies [name.Name] = asm;
}
return asm;
}
public void CacheAssembly (AssemblyDefinition assembly)
{
_assemblies [assembly.Name.Name] = assembly;
base.AddSearchDirectory (Path.GetDirectoryName (assembly.MainModule.FullyQualifiedName));
}
}
}

View File

@@ -0,0 +1,322 @@
//
// Driver.cs
//
// Author:
// Jb Evain (jbevain@gmail.com)
//
// (C) 2006 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.
//
using System;
using System.Collections;
using System.IO;
using SR = System.Reflection;
using System.Xml.XPath;
using Mono.Linker.Steps;
namespace Mono.Linker {
public class Driver {
static readonly string _linker = "Mono CIL Linker";
public static int Main (string [] args)
{
if (args.Length == 0)
Usage ("No parameters specified");
try {
Driver driver = new Driver (args);
driver.Run ();
} catch (Exception e) {
Console.WriteLine ("Fatal error in {0}", _linker);
Console.WriteLine (e);
return 1;
}
return 0;
}
Queue _queue;
public Driver (string [] args)
{
_queue = new Queue (args);
}
bool HaveMoreTokens ()
{
return _queue.Count > 0;
}
void Run ()
{
Pipeline p = GetStandardPipeline ();
LinkContext context = GetDefaultContext (p);
I18nAssemblies assemblies = I18nAssemblies.All;
ArrayList custom_steps = new ArrayList ();
bool resolver = false;
while (HaveMoreTokens ()) {
string token = GetParam ();
if (token.Length < 2)
Usage ("Option is too short");
if (! (token [0] == '-' || token [1] == '/'))
Usage ("Expecting an option, got instead: " + token);
if (token [0] == '-' && token [1] == '-') {
if (token.Length < 3)
Usage ("Option is too short");
switch (token [2]) {
case 'v':
Version ();
break;
case 'a':
About ();
break;
default:
Usage (null);
break;
}
}
switch (token [1]) {
case 'd': {
DirectoryInfo info = new DirectoryInfo (GetParam ());
context.Resolver.AddSearchDirectory (info.FullName);
break;
}
case 'o':
context.OutputDirectory = GetParam ();
break;
case 'c':
context.CoreAction = ParseAssemblyAction (GetParam ());
break;
case 'p':
AssemblyAction action = ParseAssemblyAction (GetParam ());
context.Actions [GetParam ()] = action;
break;
case 's':
custom_steps.Add (GetParam ());
break;
case 'x':
foreach (string file in GetFiles (GetParam ()))
p.PrependStep (new ResolveFromXmlStep (new XPathDocument (file)));
resolver = true;
break;
case 'a':
foreach (string file in GetFiles (GetParam ()))
p.PrependStep (new ResolveFromAssemblyStep (file));
resolver = true;
break;
case 'i':
foreach (string file in GetFiles (GetParam ()))
p.PrependStep (new ResolveFromXApiStep (new XPathDocument (file)));
resolver = true;
break;
case 'l':
assemblies = ParseI18n (GetParam ());
break;
case 'm':
context.SetParameter (GetParam (), GetParam ());
break;
case 'b':
context.LinkSymbols = bool.Parse (GetParam ());
break;
case 'g':
if (!bool.Parse (GetParam ()))
p.RemoveStep (typeof (RegenerateGuidStep));
break;
default:
Usage ("Unknown option: `" + token [1] + "'");
break;
}
}
if (!resolver)
Usage ("No resolver was created (use -x, -a or -i)");
foreach (string custom_step in custom_steps)
AddCustomStep (p, custom_step);
p.AddStepAfter (typeof (LoadReferencesStep), new LoadI18nAssemblies (assemblies));
p.Process (context);
}
static void AddCustomStep (Pipeline pipeline, string arg)
{
int pos = arg.IndexOf (":");
if (pos == -1) {
pipeline.AppendStep (ResolveStep (arg));
return;
}
string [] parts = arg.Split (':');
if (parts.Length != 2)
Usage ("Step is specified as TYPE:STEP");
if (parts [0].IndexOf (",") > -1)
pipeline.AddStepBefore (FindStep (pipeline, parts [1]), ResolveStep (parts [0]));
else if (parts [1].IndexOf (",") > -1)
pipeline.AddStepAfter (FindStep (pipeline, parts [0]), ResolveStep (parts [1]));
else
Usage ("No comma separator in TYPE or STEP");
}
static Type FindStep (Pipeline pipeline, string name)
{
foreach (IStep step in pipeline.GetSteps ()) {
Type t = step.GetType ();
if (t.Name == name)
return t;
}
return null;
}
static IStep ResolveStep (string type)
{
Type step = Type.GetType (type, false);
if (step == null)
Usage (String.Format ("Step type '{0}' not found.", type));
if (!typeof (IStep).IsAssignableFrom (step))
Usage (String.Format ("Step type '{0}' does not implement IStep interface.", type));
return (IStep) Activator.CreateInstance (step);
}
static string [] GetFiles (string param)
{
if (param.Length < 1 || param [0] != '@')
return new string [] {param};
string file = param.Substring (1);
return ReadLines (file);
}
static string [] ReadLines (string file)
{
ArrayList lines = new ArrayList ();
using (StreamReader reader = new StreamReader (file)) {
string line;
while ((line = reader.ReadLine ()) != null)
lines.Add (line);
}
return (string []) lines.ToArray (typeof (string));
}
static I18nAssemblies ParseI18n (string str)
{
I18nAssemblies assemblies = I18nAssemblies.None;
string [] parts = str.Split (',');
foreach (string part in parts)
assemblies |= (I18nAssemblies) Enum.Parse (typeof (I18nAssemblies), part.Trim (), true);
return assemblies;
}
static AssemblyAction ParseAssemblyAction (string s)
{
return (AssemblyAction) Enum.Parse (typeof (AssemblyAction), s, true);
}
string GetParam ()
{
if (_queue.Count == 0)
Usage ("Expecting a parameter");
return (string) _queue.Dequeue ();
}
static LinkContext GetDefaultContext (Pipeline pipeline)
{
LinkContext context = new LinkContext (pipeline);
context.CoreAction = AssemblyAction.Skip;
context.OutputDirectory = "output";
return context;
}
static void Usage (string msg)
{
Console.WriteLine (_linker);
if (msg != null)
Console.WriteLine ("Error: " + msg);
Console.WriteLine ("monolinker [options] -x|-a|-i file");
Console.WriteLine (" --about About the {0}", _linker);
Console.WriteLine (" --version Print the version number of the {0}", _linker);
Console.WriteLine (" -out Specify the output directory, default to `output'");
Console.WriteLine (" -c Action on the core assemblies, skip, copy or link, default to skip");
Console.WriteLine (" -p Action per assembly");
Console.WriteLine (" -s Add a new step to the pipeline.");
Console.WriteLine (" -d Add a directory where the linker will look for assemblies");
Console.WriteLine (" -b Generate debug symbols for each linked module (true or false)");
Console.WriteLine (" -g Generate a new unique guid for each linked module (true or false)");
Console.WriteLine (" -l List of i18n assemblies to copy to the output directory");
Console.WriteLine (" separated with a comma: none,all,cjk,mideast,other,rare,west");
Console.WriteLine (" default is all");
Console.WriteLine (" -x Link from an XML descriptor");
Console.WriteLine (" -a Link from a list of assemblies");
Console.WriteLine (" -i Link from an mono-api-info descriptor");
Console.WriteLine ("");
Environment.Exit (1);
}
static void Version ()
{
Console.WriteLine ("{0} Version {1}",
_linker,
System.Reflection.Assembly.GetExecutingAssembly ().GetName ().Version);
Environment.Exit(1);
}
static void About ()
{
Console.WriteLine ("For more information, visit the project Web site");
Console.WriteLine (" http://www.mono-project.com/");
Environment.Exit(1);
}
static Pipeline GetStandardPipeline ()
{
Pipeline p = new Pipeline ();
p.AppendStep (new LoadReferencesStep ());
p.AppendStep (new BlacklistStep ());
p.AppendStep (new TypeMapStep ());
p.AppendStep (new MarkStep ());
p.AppendStep (new SweepStep ());
p.AppendStep (new CleanStep ());
p.AppendStep (new RegenerateGuidStep ());
p.AppendStep (new OutputStep ());
return p;
}
}
}

View File

@@ -0,0 +1,47 @@
//
// I18nAssemblies.cs
//
// Author:
// Jb Evain (jbevain@novell.com)
//
// (C) 2007 Novell, Inc.
//
// 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.
//
using System;
namespace Mono.Linker {
[Flags]
public enum I18nAssemblies {
None = 0,
CJK = 1,
MidEast = 2,
Other = 4,
Rare = 8,
West = 16,
All = CJK | MidEast | Other | Rare | West,
Base
}
}

View File

@@ -0,0 +1,47 @@
//
// XApiVisitor.cs
//
// Author:
// Jb Evain (jbevain@novell.com)
//
// (C) 2007 Novell, Inc.
//
// 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.
//
using System.Xml.XPath;
using Mono.Cecil;
namespace Mono.Linker {
public interface IXApiVisitor {
void OnAssembly (XPathNavigator nav, AssemblyDefinition assembly);
void OnAttribute (XPathNavigator nav);
void OnClass (XPathNavigator nav, TypeDefinition type);
void OnInterface (XPathNavigator nav, TypeDefinition type);
void OnField (XPathNavigator nav, FieldDefinition field);
void OnMethod (XPathNavigator nav, MethodDefinition method);
void OnConstructor (XPathNavigator nav, MethodDefinition method);
void OnProperty (XPathNavigator nav, PropertyDefinition property);
void OnEvent (XPathNavigator nav, EventDefinition evt);
}
}

View File

@@ -0,0 +1,250 @@
//
// LinkContext.cs
//
// Author:
// Jb Evain (jbevain@gmail.com)
//
// (C) 2006 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.
//
using System;
using System.Collections;
using System.IO;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace Mono.Linker {
public class LinkContext {
Pipeline _pipeline;
AssemblyAction _coreAction;
Hashtable _actions;
string _outputDirectory;
Hashtable _parameters;
bool _linkSymbols;
AssemblyResolver _resolver;
ReaderParameters _readerParameters;
ISymbolReaderProvider _symbolReaderProvider;
ISymbolWriterProvider _symbolWriterProvider;
AnnotationStore _annotations;
public Pipeline Pipeline {
get { return _pipeline; }
}
public AnnotationStore Annotations {
get { return _annotations; }
}
public string OutputDirectory {
get { return _outputDirectory; }
set { _outputDirectory = value; }
}
public AssemblyAction CoreAction {
get { return _coreAction; }
set { _coreAction = value; }
}
public bool LinkSymbols {
get { return _linkSymbols; }
set { _linkSymbols = value; }
}
public IDictionary Actions {
get { return _actions; }
}
public AssemblyResolver Resolver {
get { return _resolver; }
}
public ISymbolReaderProvider SymbolReaderProvider {
get { return _symbolReaderProvider; }
set { _symbolReaderProvider = value; }
}
public ISymbolWriterProvider SymbolWriterProvider {
get { return _symbolWriterProvider; }
set { _symbolWriterProvider = value; }
}
public LinkContext (Pipeline pipeline)
: this (pipeline, new AssemblyResolver ())
{
}
public LinkContext (Pipeline pipeline, AssemblyResolver resolver)
{
_pipeline = pipeline;
_resolver = resolver;
_actions = new Hashtable ();
_parameters = new Hashtable ();
_annotations = new AnnotationStore ();
_readerParameters = new ReaderParameters {
AssemblyResolver = _resolver,
};
}
public TypeDefinition GetType (string fullName)
{
int pos = fullName.IndexOf (",");
fullName = fullName.Replace ("+", "/");
if (pos == -1) {
foreach (AssemblyDefinition asm in GetAssemblies ()) {
var type = asm.MainModule.GetType (fullName);
if (type != null)
return type;
}
return null;
}
string asmname = fullName.Substring (pos + 1);
fullName = fullName.Substring (0, pos);
AssemblyDefinition assembly = Resolve (AssemblyNameReference.Parse (asmname));
return assembly.MainModule.GetType (fullName);
}
public AssemblyDefinition Resolve (string name)
{
if (File.Exists (name)) {
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly (name, _readerParameters);
_resolver.CacheAssembly (assembly);
return assembly;
}
return Resolve (new AssemblyNameReference (name, new Version ()));
}
public AssemblyDefinition Resolve (IMetadataScope scope)
{
AssemblyNameReference reference = GetReference (scope);
try {
AssemblyDefinition assembly = _resolver.Resolve (reference, _readerParameters);
if (SeenFirstTime (assembly)) {
SafeReadSymbols (assembly);
SetAction (assembly);
}
return assembly;
}
catch {
throw new AssemblyResolutionException (reference);
}
}
bool SeenFirstTime (AssemblyDefinition assembly)
{
return !_annotations.HasAction (assembly);
}
public void SafeReadSymbols (AssemblyDefinition assembly)
{
if (!_linkSymbols)
return;
if (assembly.MainModule.HasSymbols)
return;
try {
if (_symbolReaderProvider != null) {
var symbolReader = _symbolReaderProvider.GetSymbolReader (
assembly.MainModule,
assembly.MainModule.FullyQualifiedName);
_annotations.AddSymbolReader (assembly, symbolReader);
assembly.MainModule.ReadSymbols (symbolReader);
} else
assembly.MainModule.ReadSymbols ();
} catch {}
}
static AssemblyNameReference GetReference (IMetadataScope scope)
{
AssemblyNameReference reference;
if (scope is ModuleDefinition) {
AssemblyDefinition asm = ((ModuleDefinition) scope).Assembly;
reference = asm.Name;
} else
reference = (AssemblyNameReference) scope;
return reference;
}
void SetAction (AssemblyDefinition assembly)
{
AssemblyAction action = AssemblyAction.Link;
AssemblyNameDefinition name = assembly.Name;
if (_actions.Contains (name.Name))
action = (AssemblyAction) _actions [name.Name];
else if (IsCore (name))
action = _coreAction;
_annotations.SetAction (assembly, action);
}
static bool IsCore (AssemblyNameReference name)
{
switch (name.Name) {
case "mscorlib":
case "Accessibility":
case "Mono.Security":
return true;
default:
return name.Name.StartsWith ("System")
|| name.Name.StartsWith ("Microsoft");
}
}
public AssemblyDefinition [] GetAssemblies ()
{
IDictionary cache = _resolver.AssemblyCache;
AssemblyDefinition [] asms = new AssemblyDefinition [cache.Count];
cache.Values.CopyTo (asms, 0);
return asms;
}
public void SetParameter (string key, string value)
{
_parameters [key] = value;
}
public bool HasParameter (string key)
{
return _parameters.Contains (key);
}
public string GetParameter (string key)
{
return (string) _parameters [key];
}
}
}

View File

@@ -0,0 +1,36 @@
//
// MethodAction.cs
//
// Author:
// Jb Evain (jbevain@gmail.com)
//
// (C) 2006 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.Linker {
public enum MethodAction {
Nothing,
Parse,
ForceParse
}
}

View File

@@ -0,0 +1,136 @@
//
// Pipeline.cs
//
// Author:
// Jb Evain (jbevain@gmail.com)
//
// (C) 2006 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.
//
using System;
using System.Collections;
using System.Diagnostics;
using Mono.Linker.Steps;
namespace Mono.Linker {
public class Pipeline {
ArrayList _steps;
public Pipeline ()
{
_steps = new ArrayList();
}
public void PrependStep (IStep step)
{
_steps.Insert (0, step);
}
public void AppendStep (IStep step)
{
_steps.Add (step);
}
public void AddStepBefore (Type target, IStep step)
{
for (int i = 0; i < _steps.Count; i++) {
if (target.IsInstanceOfType (_steps [i])) {
_steps.Insert (i, step);
return;
}
}
string msg = String.Format ("Step {0} could not be inserted before (not found) {1}", step, target);
throw new InvalidOperationException (msg);
}
public void ReplaceStep (Type target, IStep step)
{
AddStepBefore (target, step);
RemoveStep (target);
}
public void AddStepAfter (Type target, IStep step)
{
for (int i = 0; i < _steps.Count; i++) {
if (target.IsInstanceOfType (_steps [i])) {
if (i == _steps.Count - 1)
_steps.Add (step);
else
_steps.Insert (i + 1, step);
return;
}
}
string msg = String.Format ("Step {0} could not be inserted after (not found) {1}", step, target);
throw new InvalidOperationException (msg);
}
public void AddStepAfter (IStep target, IStep step)
{
for (int i = 0; i < _steps.Count; i++) {
if (_steps [i] == target) {
if (i == _steps.Count - 1)
_steps.Add (step);
else
_steps.Insert (i + 1, step);
return;
}
}
}
public void RemoveStep (Type target)
{
for (int i = 0; i < _steps.Count; i++) {
if (_steps [i].GetType () != target)
continue;
_steps.RemoveAt (i);
break;
}
}
public void Process (LinkContext context)
{
while (_steps.Count > 0) {
IStep step = (IStep) _steps [0];
step.Process (context);
_steps.Remove (step);
}
}
public IStep [] GetSteps ()
{
return (IStep []) _steps.ToArray (typeof (IStep));
}
public bool ContainsStep (Type type)
{
foreach (IStep step in _steps)
if (step.GetType () == type)
return true;
return false;
}
}
}

View File

@@ -0,0 +1,37 @@
//
// TypePreserve.cs
//
// Author:
// Jb Evain (jb@nurv.fr)
//
// (C) 2007 Novell, Inc.
//
// 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.Linker {
public enum TypePreserve {
Nothing,
All,
Fields,
Methods,
}
}

View File

@@ -0,0 +1,383 @@
//
// XApiReader.cs
//
// Author:
// Jb Evain (jbevain@novell.com)
//
// (C) 2007 Novell, Inc.
//
// 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.
//
using System;
using System.Collections;
using System.Linq;
using System.Text;
using System.Xml.XPath;
using Mono.Cecil;
namespace Mono.Linker {
public class XApiReader {
static readonly string _name = "name";
static readonly string _ns = string.Empty;
LinkContext _context;
XPathDocument _document;
IXApiVisitor _visitor;
AssemblyDefinition _assembly;
string _namespace;
Stack _types = new Stack ();
StringBuilder _signature;
public XApiReader (XPathDocument document, IXApiVisitor visitor)
{
_document = document;
_visitor = visitor;
}
public void Process (LinkContext context)
{
_context = context;
ProcessAssemblies (_document.CreateNavigator ());
}
void OnAssembly (XPathNavigator nav)
{
_assembly = GetAssembly (nav);
_visitor.OnAssembly (nav, _assembly);
ProcessAttributes (nav);
ProcessNamespaces (nav);
}
AssemblyDefinition GetAssembly (XPathNavigator nav)
{
AssemblyNameReference name = new AssemblyNameReference (
GetName (nav),
new Version (GetAttribute (nav, "version")));
AssemblyDefinition assembly = _context.Resolve (name);
ProcessReferences (assembly);
return assembly;
}
void ProcessReferences (AssemblyDefinition assembly)
{
foreach (AssemblyNameReference name in assembly.MainModule.AssemblyReferences)
_context.Resolve (name);
}
void OnAttribute (XPathNavigator nav)
{
_visitor.OnAttribute (nav);
}
void PushType (TypeDefinition type)
{
_types.Push (type);
}
TypeDefinition PeekType ()
{
return (TypeDefinition) _types.Peek ();
}
TypeDefinition PopType ()
{
return (TypeDefinition) _types.Pop ();
}
void OnNamespace (XPathNavigator nav)
{
_namespace = GetName (nav);
ProcessClasses (nav);
}
void OnClass (XPathNavigator nav)
{
string name = GetClassName (nav);
TypeDefinition type = _assembly.MainModule.GetType (name);
if (type == null)
return;
_visitor.OnClass (nav, type);
PushType (type);
ProcessAttributes (nav);
ProcessInterfaces (nav);
ProcessFields (nav);
ProcessMethods (nav);
ProcessConstructors (nav);
ProcessProperties (nav);
ProcessEvents (nav);
ProcessClasses (nav);
PopType ();
}
string GetClassName (XPathNavigator nav)
{
if (IsNestedClass ())
return PeekType ().FullName + "/" + GetName (nav);
return _namespace + "." + GetName (nav);
}
bool IsNestedClass ()
{
return _types.Count > 0;
}
void OnField (XPathNavigator nav)
{
TypeDefinition declaring = PeekType ();
FieldDefinition field = declaring.Fields.FirstOrDefault (f => f.Name == GetName (nav));
if (field != null)
_visitor.OnField (nav, field);
ProcessAttributes (nav);
}
void OnInterface (XPathNavigator nav)
{
string name = GetName (nav);
TypeDefinition type = _context.GetType (GetTypeName (name));
if (type != null)
_visitor.OnInterface (nav, type);
}
void OnMethod (XPathNavigator nav)
{
InitMethodSignature (nav);
ProcessParameters (nav);
string signature = GetMethodSignature ();
MethodDefinition method = GetMethod (signature);
if (method != null)
_visitor.OnMethod (nav, method);
ProcessAttributes (nav);
}
MethodDefinition GetMethod (string signature)
{
return GetMethod (PeekType ().Methods, signature);
}
static MethodDefinition GetMethod (ICollection methods, string signature)
{
foreach (MethodDefinition method in methods)
if (signature == GetSignature (method))
return method;
return null;
}
static string GetSignature (MethodDefinition method)
{
return method.ToString ().Replace ("<", "[").Replace (">", "]");
}
string GetMethodSignature ()
{
_signature.Append (")");
return _signature.ToString ();
}
void InitMethodSignature (XPathNavigator nav)
{
_signature = new StringBuilder ();
string returntype = GetAttribute (nav, "returntype");
if (returntype == null || returntype.Length == 0)
returntype = "System.Void";
_signature.Append (NormalizeTypeName (returntype));
_signature.Append (" ");
_signature.Append (PeekType ().FullName);
_signature.Append ("::");
string name = GetName (nav);
_signature.Append (GetMethodName (name));
_signature.Append ("(");
}
static string GetMethodName (string name)
{
return GetStringBefore (name, "(");
}
static string NormalizeTypeName (string name)
{
return name.Replace ("+", "/").Replace ("<", "[").Replace (">", "]");
}
static string GetTypeName (string name)
{
return GetStringBefore (NormalizeTypeName (name), "[");
}
static string GetStringBefore (string str, string marker)
{
int pos = str.IndexOf (marker);
if (pos == -1)
return str;
return str.Substring (0, pos);
}
void OnParameter (XPathNavigator nav)
{
string type = GetAttribute (nav, "type");
int pos = int.Parse (GetAttribute (nav, "position"));
if (pos > 0)
_signature.Append (",");
_signature.Append (NormalizeTypeName (type));
}
void OnConstructor (XPathNavigator nav)
{
InitMethodSignature (nav);
ProcessParameters (nav);
string signature = GetMethodSignature ();
MethodDefinition ctor = GetMethod (signature);
if (ctor != null)
_visitor.OnConstructor (nav, ctor);
ProcessAttributes (nav);
}
void OnProperty (XPathNavigator nav)
{
string name = GetName (nav);
TypeDefinition type = PeekType ();
var property = type.Properties.FirstOrDefault (p => p.Name == name);
if (property != null)
_visitor.OnProperty (nav, property);
ProcessAttributes (nav);
ProcessMethods (nav);
}
void OnEvent (XPathNavigator nav)
{
string name = GetName (nav);
TypeDefinition type = PeekType ();
EventDefinition evt = type.Events.FirstOrDefault (e => e.Name == name);
if (evt != null)
_visitor.OnEvent (nav, evt);
ProcessAttributes (nav);
}
void ProcessAssemblies (XPathNavigator nav)
{
ProcessChildren (nav, "assemblies//assembly", new OnChildren (OnAssembly));
}
void ProcessAttributes (XPathNavigator nav)
{
ProcessChildren (nav, "attributes//attribute", new OnChildren (OnAttribute));
}
void ProcessNamespaces (XPathNavigator nav)
{
ProcessChildren (nav, "namespaces//namespace", new OnChildren (OnNamespace));
}
void ProcessClasses (XPathNavigator nav)
{
ProcessChildren (nav, "classes//class", new OnChildren (OnClass));
}
void ProcessInterfaces (XPathNavigator nav)
{
ProcessChildren (nav, "intefaces//interface", new OnChildren (OnInterface));
}
void ProcessFields (XPathNavigator nav)
{
ProcessChildren (nav, "fields//field", new OnChildren (OnField));
}
void ProcessMethods (XPathNavigator nav)
{
ProcessChildren (nav, "methods//method", new OnChildren (OnMethod));
}
void ProcessConstructors (XPathNavigator nav)
{
ProcessChildren (nav, "constructors//constructor", new OnChildren (OnConstructor));
}
void ProcessParameters (XPathNavigator nav)
{
ProcessChildren (nav, "parameters//parameter", new OnChildren (OnParameter));
}
void ProcessProperties (XPathNavigator nav)
{
ProcessChildren (nav, "properties//property", new OnChildren (OnProperty));
}
void ProcessEvents (XPathNavigator nav)
{
ProcessChildren (nav, "events//event", new OnChildren (OnEvent));
}
static void ProcessChildren (XPathNavigator nav, string children, OnChildren action)
{
XPathNodeIterator iterator = nav.Select (children);
while (iterator.MoveNext ())
action (iterator.Current);
}
delegate void OnChildren (XPathNavigator nav);
static string GetName (XPathNavigator nav)
{
return GetAttribute (nav, _name);
}
static string GetAttribute (XPathNavigator nav, string attribute)
{
return nav.GetAttribute (attribute, _ns);
}
}
}