This repository has been archived by the owner on Feb 8, 2018. It is now read-only.
forked from gluck/ikvm
-
Notifications
You must be signed in to change notification settings - Fork 5
/
vm.cs
290 lines (270 loc) · 7.31 KB
/
vm.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/*
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jeroen Frijters
jeroen@frijters.net
*/
using System;
using System.Threading;
using System.Reflection;
using System.IO;
using System.Collections;
using System.Diagnostics;
using System.Text;
using System.Security;
using System.Security.Permissions;
using IKVM.Attributes;
using IKVM.Internal;
#if !STATIC_COMPILER && !COMPACT_FRAMEWORK
namespace IKVM.Internal
{
public sealed class Starter
{
private Starter() {}
public static void PrepareForSaveDebugImage()
{
JVM.IsSaveDebugImage = true;
}
public static void SaveDebugImage()
{
DynamicClassLoader.Instance.SaveDebugImage();
}
public static bool EnableReflectionOnMethodsWithUnloadableTypeParameters
{
get
{
return JVM.EnableReflectionOnMethodsWithUnloadableTypeParameters;
}
set
{
JVM.EnableReflectionOnMethodsWithUnloadableTypeParameters = value;
}
}
}
}
#endif // !STATIC_COMPILER && !COMPACT_FRAMEWORK
namespace IKVM.Internal
{
class JVM
{
#if STATIC_COMPILER
internal const bool IsStaticCompiler = true;
internal const bool FinishingForDebugSave = false;
internal const bool IsSaveDebugImage = false;
#else
internal const bool IsStaticCompiler = false;
private static bool enableReflectionOnMethodsWithUnloadableTypeParameters;
private static bool finishingForDebugSave;
#if !FIRST_PASS
private static ikvm.@internal.LibraryVMInterface lib;
#endif
internal static bool IsSaveDebugImage;
#endif // STATIC_COMPILER
private static Assembly coreAssembly;
internal static Version SafeGetAssemblyVersion(Assembly asm)
{
// Assembly.GetName().Version requires FileIOPermission,
// so we parse the FullName manually :-(
string name = asm.FullName;
int start = name.IndexOf(", Version=");
if(start >= 0)
{
start += 10;
int end = name.IndexOf(',', start);
if(end >= 0)
{
return new Version(name.Substring(start, end - start));
}
}
return new Version();
}
internal static string SafeGetEnvironmentVariable(string name)
{
try
{
return Environment.GetEnvironmentVariable(name);
}
catch(SecurityException)
{
return null;
}
}
internal static Assembly CoreAssembly
{
get
{
#if !STATIC_COMPILER
if(coreAssembly == null)
{
#if FIRST_PASS
throw new InvalidOperationException("This version of IKVM.Runtime.dll was compiled with FIRST_PASS defined.");
#else
coreAssembly = typeof(ikvm.@internal.Library).Assembly;
#endif
}
#endif // !STATIC_COMPILER
return coreAssembly;
}
set
{
coreAssembly = value;
}
}
#if !STATIC_COMPILER
internal static ikvm.@internal.LibraryVMInterface Library
{
get
{
#if FIRST_PASS
throw new InvalidOperationException("This version of IKVM.Runtime.dll was compiled with FIRST_PASS defined.");
#else
if(lib == null)
{
lib = ikvm.@internal.Library.getImpl();
}
return lib;
#endif
}
}
public static bool EnableReflectionOnMethodsWithUnloadableTypeParameters
{
get
{
return enableReflectionOnMethodsWithUnloadableTypeParameters;
}
set
{
enableReflectionOnMethodsWithUnloadableTypeParameters = value;
}
}
internal static bool FinishingForDebugSave
{
get
{
return finishingForDebugSave;
}
set
{
finishingForDebugSave = value;
}
}
#endif // !STATIC_COMPILER
internal static bool IsUnix
{
get
{
#if WHIDBEY
return Environment.OSVersion.Platform == PlatformID.Unix;
#else
PlatformID pid = Environment.OSVersion.Platform;
return pid != PlatformID.Win32NT && pid != PlatformID.Win32S && pid != PlatformID.Win32Windows && pid != PlatformID.WinCE;
#endif
}
}
internal static string MangleResourceName(string name)
{
// FXBUG there really shouldn't be any need to mangle the resource names,
// but in order for ILDASM/ILASM round tripping to work reliably, we have
// to make sure that we don't produce resource names that'll cause ILDASM
// to generate invalid filenames.
StringBuilder sb = new StringBuilder("ikvm__", name.Length + 6);
foreach(char c in name)
{
if("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+.()$#@~=&{}[]0123456789`".IndexOf(c) != -1)
{
sb.Append(c);
}
else if(c == '/')
{
sb.Append('!');
}
else
{
sb.Append('%');
sb.Append(string.Format("{0:X4}", (int)c));
}
}
return sb.ToString();
}
internal static void CriticalFailure(string message, Exception x)
{
try
{
Tracer.Error(Tracer.Runtime, "CRITICAL FAILURE: {0}", message);
Type messageBox = null;
#if !STATIC_COMPILER
// NOTE we use reflection to invoke MessageBox.Show, to make sure we run in environments where WinForms isn't available
Assembly winForms = IsUnix ? null : Assembly.Load("System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
if(winForms != null)
{
messageBox = winForms.GetType("System.Windows.Forms.MessageBox");
}
#endif
new ReflectionPermission(ReflectionPermissionFlag.MemberAccess
#if !WHIDBEY
| ReflectionPermissionFlag.TypeInformation
#endif
).Assert();
message = String.Format("****** Critical Failure: {1} ******{0}{0}" +
"PLEASE FILE A BUG REPORT FOR IKVM.NET WHEN YOU SEE THIS MESSAGE{0}{0}" +
(messageBox != null ? "(on Windows you can use Ctrl+C to copy the contents of this message to the clipboard){0}{0}" : "") +
"{2}{0}" +
"{3}{0}" +
"{4}",
Environment.NewLine,
message,
x,
x != null ? new StackTrace(x, true).ToString() : "",
new StackTrace(true));
CodeAccessPermission.RevertAssert();
if(messageBox != null)
{
try
{
Version ver = SafeGetAssemblyVersion(typeof(JVM).Assembly);
messageBox.InvokeMember("Show", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, null, null, new object[] { message, "IKVM.NET " + ver + " Critical Failure" });
}
catch
{
Console.Error.WriteLine(message);
}
}
else
{
Console.Error.WriteLine(message);
}
}
catch(Exception ex)
{
Console.Error.WriteLine(ex);
}
finally
{
Environment.Exit(666);
}
}
// this method resolves types in IKVM.Runtime.dll
// (the version of IKVM.Runtime.dll that we're running
// with can be different from the one we're compiling against.)
internal static Type LoadType(Type type)
{
#if WHIDBEY && STATIC_COMPILER
return StaticCompiler.GetType(type.FullName);
#else
return type;
#endif
}
}
}