b9d29169c896d2758b69f2433454468bbde9f5fd
[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
33 using Mono.Cecil;
34 using Mono.Cecil.Cil;
35
36 namespace Mono.Linker {
37
38         public class LinkContext {
39
40                 Pipeline _pipeline;
41                 AssemblyAction _coreAction;
42                 Hashtable _actions;
43                 string _outputDirectory;
44                 Hashtable _parameters;
45                 bool _linkSymbols;
46
47                 AssemblyResolver _resolver;
48
49                 ReaderParameters _readerParameters;
50                 ISymbolReaderProvider _symbolReaderProvider;
51                 ISymbolWriterProvider _symbolWriterProvider;
52
53                 AnnotationStore _annotations;
54
55                 public Pipeline Pipeline {
56                         get { return _pipeline; }
57                 }
58
59                 public AnnotationStore Annotations {
60                         get { return _annotations; }
61                 }
62
63                 public string OutputDirectory {
64                         get { return _outputDirectory; }
65                         set { _outputDirectory = value; }
66                 }
67
68                 public AssemblyAction CoreAction {
69                         get { return _coreAction; }
70                         set { _coreAction = value; }
71                 }
72
73                 public bool LinkSymbols {
74                         get { return _linkSymbols; }
75                         set { _linkSymbols = value; }
76                 }
77
78                 public IDictionary Actions {
79                         get { return _actions; }
80                 }
81
82                 public AssemblyResolver Resolver {
83                         get { return _resolver; }
84                 }
85
86                 public ISymbolReaderProvider SymbolReaderProvider {
87                         get { return _symbolReaderProvider; }
88                         set {
89                                 _symbolReaderProvider = value;
90                                 _readerParameters.SymbolReaderProvider = value;
91                         }
92                 }
93
94                 public ISymbolWriterProvider SymbolWriterProvider {
95                         get { return _symbolWriterProvider; }
96                         set { _symbolWriterProvider = value; }
97                 }
98
99                 public LinkContext (Pipeline pipeline)
100                         : this (pipeline, new AssemblyResolver ())
101                 {
102                 }
103
104                 public LinkContext (Pipeline pipeline, AssemblyResolver resolver)
105                 {
106                         _pipeline = pipeline;
107                         _resolver = resolver;
108                         _actions = new Hashtable ();
109                         _parameters = new Hashtable ();
110                         _annotations = new AnnotationStore ();
111                         _readerParameters = new ReaderParameters {
112                                 AssemblyResolver = _resolver,
113                         };
114                 }
115
116                 public TypeDefinition GetType (string fullName)
117                 {
118                         int pos = fullName.IndexOf (",");
119                         fullName = fullName.Replace ("+", "/");
120                         if (pos == -1) {
121                                 foreach (AssemblyDefinition asm in GetAssemblies ()) {
122                                         var type = asm.MainModule.GetType (fullName);
123                                         if (type != null)
124                                                 return type;
125                                 }
126
127                                 return null;
128                         }
129
130                         string asmname = fullName.Substring (pos + 1);
131                         fullName = fullName.Substring (0, pos);
132                         AssemblyDefinition assembly = Resolve (AssemblyNameReference.Parse (asmname));
133                         return assembly.MainModule.GetType (fullName);
134                 }
135
136                 public AssemblyDefinition Resolve (string name)
137                 {
138                         if (File.Exists (name)) {
139                                 AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly (name, _readerParameters);
140                                 _resolver.CacheAssembly (assembly);
141                                 return assembly;
142                         }
143
144                         return Resolve (new AssemblyNameReference (name, new Version ()));
145                 }
146
147                 public AssemblyDefinition Resolve (IMetadataScope scope)
148                 {
149                         AssemblyNameReference reference = GetReference (scope);
150
151                         AssemblyDefinition assembly = _resolver.Resolve (reference, _readerParameters);
152
153                         if (SeenFirstTime (assembly)) {
154                                 SafeReadSymbols (assembly);
155                                 SetAction (assembly);
156                         }
157
158                         return assembly;
159                 }
160
161                 bool SeenFirstTime (AssemblyDefinition assembly)
162                 {
163                         return !_annotations.HasAction (assembly);
164                 }
165
166                 public void SafeReadSymbols (AssemblyDefinition assembly)
167                 {
168                         if (!_linkSymbols)
169                                 return;
170
171                         try {
172                                 if (_symbolReaderProvider != null) {
173                                         var symbolReader = _symbolReaderProvider.GetSymbolReader (
174                                                 assembly.MainModule,
175                                                 assembly.MainModule.FullyQualifiedName);
176
177                                         _annotations.AddSymbolReader (assembly, symbolReader);
178                                         assembly.MainModule.ReadSymbols (symbolReader);
179                                 } else
180                                         assembly.MainModule.ReadSymbols ();
181                         } catch {}
182                 }
183
184                 static AssemblyNameReference GetReference (IMetadataScope scope)
185                 {
186                         AssemblyNameReference reference;
187                         if (scope is ModuleDefinition) {
188                                 AssemblyDefinition asm = ((ModuleDefinition) scope).Assembly;
189                                 reference = asm.Name;
190                         } else
191                                 reference = (AssemblyNameReference) scope;
192
193                         return reference;
194                 }
195
196                 void SetAction (AssemblyDefinition assembly)
197                 {
198                         AssemblyAction action = AssemblyAction.Link;
199
200                         AssemblyNameDefinition name = assembly.Name;
201
202                         if (_actions.Contains (name.Name))
203                                 action = (AssemblyAction) _actions [name.Name];
204                         else if (IsCore (name))
205                                 action = _coreAction;
206
207                         _annotations.SetAction (assembly, action);
208                 }
209
210                 static bool IsCore (AssemblyNameReference name)
211                 {
212                         switch (name.Name) {
213                         case "mscorlib":
214                         case "Accessibility":
215                         case "Mono.Security":
216                                 return true;
217                         default:
218                                 return name.Name.StartsWith ("System")
219                                         || name.Name.StartsWith ("Microsoft");
220                         }
221                 }
222
223                 public AssemblyDefinition [] GetAssemblies ()
224                 {
225                         IDictionary cache = _resolver.AssemblyCache;
226                         AssemblyDefinition [] asms = new AssemblyDefinition [cache.Count];
227                         cache.Values.CopyTo (asms, 0);
228                         return asms;
229                 }
230
231                 public void SetParameter (string key, string value)
232                 {
233                         _parameters [key] = value;
234                 }
235
236                 public bool HasParameter (string key)
237                 {
238                         return _parameters.Contains (key);
239                 }
240
241                 public string GetParameter (string key)
242                 {
243                         return (string) _parameters [key];
244                 }
245         }
246 }