7d7908f2ec37e944bad42ab297b54b2f997dbb79
[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 { _symbolReaderProvider = value; }
89                 }
90
91                 public ISymbolWriterProvider SymbolWriterProvider {
92                         get { return _symbolWriterProvider; }
93                         set { _symbolWriterProvider = value; }
94                 }
95
96                 public bool LogInternalExceptions { get; set; } = false;
97
98                 public LinkContext (Pipeline pipeline)
99                         : this (pipeline, new AssemblyResolver ())
100                 {
101                 }
102
103                 public LinkContext (Pipeline pipeline, AssemblyResolver resolver)
104                 {
105                         _pipeline = pipeline;
106                         _resolver = resolver;
107                         _actions = new Hashtable ();
108                         _parameters = new Hashtable ();
109                         _annotations = new AnnotationStore ();
110                         _readerParameters = new ReaderParameters {
111                                 AssemblyResolver = _resolver,
112                         };
113                 }
114
115                 public TypeDefinition GetType (string fullName)
116                 {
117                         int pos = fullName.IndexOf (",");
118                         fullName = fullName.Replace ("+", "/");
119                         if (pos == -1) {
120                                 foreach (AssemblyDefinition asm in GetAssemblies ()) {
121                                         var type = asm.MainModule.GetType (fullName);
122                                         if (type != null)
123                                                 return type;
124                                 }
125
126                                 return null;
127                         }
128
129                         string asmname = fullName.Substring (pos + 1);
130                         fullName = fullName.Substring (0, pos);
131                         AssemblyDefinition assembly = Resolve (AssemblyNameReference.Parse (asmname));
132                         return assembly.MainModule.GetType (fullName);
133                 }
134
135                 public AssemblyDefinition Resolve (string name)
136                 {
137                         if (File.Exists (name)) {
138                                 AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly (name, _readerParameters);
139                                 _resolver.CacheAssembly (assembly);
140                                 return assembly;
141                         }
142
143                         return Resolve (new AssemblyNameReference (name, new Version ()));
144                 }
145
146                 public AssemblyDefinition Resolve (IMetadataScope scope)
147                 {
148                         AssemblyNameReference reference = GetReference (scope);
149                         try {
150                                 AssemblyDefinition assembly = _resolver.Resolve (reference, _readerParameters);
151
152                                 if (SeenFirstTime (assembly)) {
153                                         SafeReadSymbols (assembly);
154                                         SetAction (assembly);
155                                 }
156
157                                 return assembly;
158                         }
159                         catch {
160                                 throw new AssemblyResolutionException (reference);
161                         }
162                 }
163
164                 bool SeenFirstTime (AssemblyDefinition assembly)
165                 {
166                         return !_annotations.HasAction (assembly);
167                 }
168
169                 public void SafeReadSymbols (AssemblyDefinition assembly)
170                 {
171                         if (!_linkSymbols)
172                                 return;
173
174                         if (assembly.MainModule.HasSymbols)
175                                 return;
176
177                         try {
178                                 if (_symbolReaderProvider != null) {
179                                         var symbolReader = _symbolReaderProvider.GetSymbolReader (
180                                                 assembly.MainModule,
181                                                 assembly.MainModule.FileName);
182
183                                         _annotations.AddSymbolReader (assembly, symbolReader);
184                                         assembly.MainModule.ReadSymbols (symbolReader);
185                                 } else
186                                         assembly.MainModule.ReadSymbols ();
187                         } catch {}
188                 }
189
190                 static AssemblyNameReference GetReference (IMetadataScope scope)
191                 {
192                         AssemblyNameReference reference;
193                         if (scope is ModuleDefinition) {
194                                 AssemblyDefinition asm = ((ModuleDefinition) scope).Assembly;
195                                 reference = asm.Name;
196                         } else
197                                 reference = (AssemblyNameReference) scope;
198
199                         return reference;
200                 }
201
202                 void SetAction (AssemblyDefinition assembly)
203                 {
204                         AssemblyAction action = AssemblyAction.Link;
205
206                         AssemblyNameDefinition name = assembly.Name;
207
208                         if (_actions.Contains (name.Name))
209                                 action = (AssemblyAction) _actions [name.Name];
210                         else if (IsCore (name))
211                                 action = _coreAction;
212
213                         _annotations.SetAction (assembly, action);
214                 }
215
216                 static bool IsCore (AssemblyNameReference name)
217                 {
218                         switch (name.Name) {
219                         case "mscorlib":
220                         case "Accessibility":
221                         case "Mono.Security":
222                                 // WPF
223                         case "PresentationFramework":
224                         case "PresentationCore":
225                         case "WindowsBase":
226                         case "UIAutomationProvider":
227                         case "UIAutomationTypes":
228                         case "PresentationUI":
229                         case "ReachFramework":
230                                 return true;
231                         default:
232                                 return name.Name.StartsWith ("System")
233                                         || name.Name.StartsWith ("Microsoft");
234                         }
235                 }
236
237                 public AssemblyDefinition [] GetAssemblies ()
238                 {
239                         IDictionary cache = _resolver.AssemblyCache;
240                         AssemblyDefinition [] asms = new AssemblyDefinition [cache.Count];
241                         cache.Values.CopyTo (asms, 0);
242                         return asms;
243                 }
244
245                 public void SetParameter (string key, string value)
246                 {
247                         _parameters [key] = value;
248                 }
249
250                 public bool HasParameter (string key)
251                 {
252                         return _parameters.Contains (key);
253                 }
254
255                 public string GetParameter (string key)
256                 {
257                         return (string) _parameters [key];
258                 }
259         }
260 }