a9ce05fb3ce59213501da86162e154f1df559975
[mono.git] / mcs / tools / linker / Mono.Linker / LinkContext.cs
1 //
2 // LinkContext.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // (C) 2006 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Collections;
31 using System.IO;
32 using Mono.Cecil;
33
34 namespace Mono.Linker {
35
36         public class LinkContext {
37
38                 Pipeline _pipeline;
39                 AssemblyAction _coreAction;
40                 Hashtable _actions;
41                 string _outputDirectory;
42                 Hashtable _parameters;
43                 bool _linkSymbols;
44
45                 AssemblyResolver _resolver;
46
47                 ReaderParameters _readerParameters;
48
49                 AnnotationStore _annotations;
50
51                 public Pipeline Pipeline {
52                         get { return _pipeline; }
53                 }
54
55                 public AnnotationStore Annotations {
56                         get { return _annotations; }
57                 }
58
59                 public string OutputDirectory {
60                         get { return _outputDirectory; }
61                         set { _outputDirectory = value; }
62                 }
63
64                 public AssemblyAction CoreAction {
65                         get { return _coreAction; }
66                         set { _coreAction = value; }
67                 }
68
69                 public bool LinkSymbols {
70                         get { return _linkSymbols; }
71                         set { _linkSymbols = value; }
72                 }
73
74                 public IDictionary Actions {
75                         get { return _actions; }
76                 }
77
78                 public AssemblyResolver Resolver {
79                         get { return _resolver; }
80                 }
81
82                 public LinkContext (Pipeline pipeline)
83                         : this (pipeline, new AssemblyResolver ())
84                 {
85                 }
86
87                 public LinkContext (Pipeline pipeline, AssemblyResolver resolver)
88                 {
89                         _pipeline = pipeline;
90                         _resolver = resolver;
91                         _actions = new Hashtable ();
92                         _parameters = new Hashtable ();
93                         _annotations = new AnnotationStore ();
94                         _readerParameters = new ReaderParameters {
95                                 AssemblyResolver = _resolver,
96                         };
97                 }
98
99                 public TypeDefinition GetType (string fullName)
100                 {
101                         int pos = fullName.IndexOf (",");
102                         fullName = fullName.Replace ("+", "/");
103                         if (pos == -1) {
104                                 foreach (AssemblyDefinition asm in GetAssemblies ()) {
105                                         var type = asm.MainModule.GetType (fullName);
106                                         if (type != null)
107                                                 return type;
108                                 }
109
110                                 return null;
111                         }
112
113                         string asmname = fullName.Substring (pos + 1);
114                         fullName = fullName.Substring (0, pos);
115                         AssemblyDefinition assembly = Resolve (AssemblyNameReference.Parse (asmname));
116                         return assembly.MainModule.GetType (fullName);
117                 }
118
119                 public AssemblyDefinition Resolve (string name)
120                 {
121                         if (File.Exists (name)) {
122                                 AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly (name, _readerParameters);
123                                 _resolver.CacheAssembly (assembly);
124                                 return assembly;
125                         }
126
127                         return Resolve (new AssemblyNameReference (name, new Version ()));
128                 }
129
130                 public AssemblyDefinition Resolve (IMetadataScope scope)
131                 {
132                         AssemblyNameReference reference = GetReference (scope);
133
134                         AssemblyDefinition assembly = _resolver.Resolve (reference, _readerParameters);
135
136                         if (SeenFirstTime (assembly)) {
137                                 SafeReadSymbols (assembly);
138                                 SetAction (assembly);
139                         }
140
141                         return assembly;
142                 }
143
144                 bool SeenFirstTime (AssemblyDefinition assembly)
145                 {
146                         return !_annotations.HasAction (assembly);
147                 }
148
149                 public void SafeReadSymbols (AssemblyDefinition assembly)
150                 {
151                         try {
152                                 assembly.MainModule.ReadSymbols ();
153                         } catch {}
154                 }
155
156                 static AssemblyNameReference GetReference (IMetadataScope scope)
157                 {
158                         AssemblyNameReference reference;
159                         if (scope is ModuleDefinition) {
160                                 AssemblyDefinition asm = ((ModuleDefinition) scope).Assembly;
161                                 reference = asm.Name;
162                         } else
163                                 reference = (AssemblyNameReference) scope;
164
165                         return reference;
166                 }
167
168                 void SetAction (AssemblyDefinition assembly)
169                 {
170                         AssemblyAction action = AssemblyAction.Link;
171
172                         AssemblyNameDefinition name = assembly.Name;
173
174                         if (_actions.Contains (name.Name))
175                                 action = (AssemblyAction) _actions [name.Name];
176                         else if (IsCore (name))
177                                 action = _coreAction;
178
179                         _annotations.SetAction (assembly, action);
180                 }
181
182                 static bool IsCore (AssemblyNameReference name)
183                 {
184                         switch (name.Name) {
185                         case "mscorlib":
186                         case "Accessibility":
187                         case "Mono.Security":
188                                 return true;
189                         default:
190                                 return name.Name.StartsWith ("System")
191                                         || name.Name.StartsWith ("Microsoft");
192                         }
193                 }
194
195                 public AssemblyDefinition [] GetAssemblies ()
196                 {
197                         IDictionary cache = _resolver.AssemblyCache;
198                         AssemblyDefinition [] asms = new AssemblyDefinition [cache.Count];
199                         cache.Values.CopyTo (asms, 0);
200                         return asms;
201                 }
202
203                 public void SetParameter (string key, string value)
204                 {
205                         _parameters [key] = value;
206                 }
207
208                 public bool HasParameter (string key)
209                 {
210                         return _parameters.Contains (key);
211                 }
212
213                 public string GetParameter (string key)
214                 {
215                         return (string) _parameters [key];
216                 }
217         }
218 }