1 /**
2  * \file
3  * Remoting support
4  *
5  * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
6  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
7  * Copyright 2011-2014 Xamarin, Inc (http://www.xamarin.com)
8  *
9  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
10  */
11 
12 #include "config.h"
13 
14 #include "mono/metadata/handle.h"
15 #include "mono/metadata/remoting.h"
16 #include "mono/metadata/marshal.h"
17 #include "mono/metadata/marshal-internals.h"
18 #include "mono/metadata/abi-details.h"
19 #include "mono/metadata/cominterop.h"
20 #include "mono/metadata/tabledefs.h"
21 #include "mono/metadata/exception.h"
22 #include "mono/metadata/debug-helpers.h"
23 #include "mono/metadata/reflection-internals.h"
24 #include "mono/metadata/assembly.h"
25 
26 typedef enum {
27 	MONO_MARSHAL_NONE,			/* No marshalling needed */
28 	MONO_MARSHAL_COPY,			/* Can be copied by value to the new domain */
29 	MONO_MARSHAL_COPY_OUT,		/* out parameter that needs to be copied back to the original instance */
30 	MONO_MARSHAL_SERIALIZE		/* Value needs to be serialized into the new domain */
31 } MonoXDomainMarshalType;
32 
33 #ifndef DISABLE_REMOTING
34 
35 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
36 	a = i,
37 
38 enum {
39 #include "mono/cil/opcode.def"
40 	LAST = 0xff
41 };
42 #undef OPDEF
43 
44 struct _MonoRemotingMethods {
45 	MonoMethod *invoke;
46 	MonoMethod *invoke_with_check;
47 	MonoMethod *xdomain_invoke;
48 	MonoMethod *xdomain_dispatch;
49 };
50 
51 typedef struct _MonoRemotingMethods MonoRemotingMethods;
52 
53 static MonoObject *
54 mono_remoting_wrapper (MonoMethod *method, gpointer *params);
55 
56 static MonoException *
57 mono_remoting_update_exception (MonoException *exc);
58 
59 static gint32
60 mono_marshal_set_domain_by_id (gint32 id, MonoBoolean push);
61 
62 static gboolean
63 mono_marshal_check_domain_image (gint32 domain_id, MonoImage *image);
64 
65 MONO_API void
66 mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy);
67 
68 static MonoXDomainMarshalType
69 mono_get_xdomain_marshal_type (MonoType *t);
70 
71 static void
72 mono_marshal_xdomain_copy_out_value (MonoObject *src, MonoObject *dst);
73 
74 static MonoReflectionType *
75 type_from_handle (MonoType *handle);
76 
77 static void
78 mono_context_set_icall (MonoAppContext *new_context);
79 
80 static MonoAppContext*
81 mono_context_get_icall (void);
82 
83 
84 /* Class lazy loading functions */
85 static GENERATE_GET_CLASS_WITH_CACHE (remoting_services, "System.Runtime.Remoting", "RemotingServices")
86 static GENERATE_GET_CLASS_WITH_CACHE (call_context, "System.Runtime.Remoting.Messaging", "CallContext")
87 static GENERATE_GET_CLASS_WITH_CACHE (context, "System.Runtime.Remoting.Contexts", "Context")
88 
89 static mono_mutex_t remoting_mutex;
90 static gboolean remoting_mutex_inited;
91 
92 static MonoClass *byte_array_class;
93 #ifndef DISABLE_JIT
94 static MonoMethod *method_rs_serialize, *method_rs_deserialize, *method_exc_fixexc, *method_rs_appdomain_target;
95 static MonoMethod *method_set_call_context, *method_needs_context_sink, *method_rs_serialize_exc;
96 #endif
97 
98 static gpointer
99 mono_compile_method_icall (MonoMethod *method);
100 
101 static void
register_icall(gpointer func,const char * name,const char * sigstr,gboolean save)102 register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
103 {
104 	MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
105 
106 	mono_register_jit_icall (func, name, sig, save);
107 }
108 
109 static inline void
remoting_lock(void)110 remoting_lock (void)
111 {
112 	g_assert (remoting_mutex_inited);
113 	mono_os_mutex_lock (&remoting_mutex);
114 }
115 
116 static inline void
remoting_unlock(void)117 remoting_unlock (void)
118 {
119 	g_assert (remoting_mutex_inited);
120 	mono_os_mutex_unlock (&remoting_mutex);
121 }
122 
123 /*
124  * Return the hash table pointed to by VAR, lazily creating it if neccesary.
125  */
126 static GHashTable*
get_cache(GHashTable ** var,GHashFunc hash_func,GCompareFunc equal_func)127 get_cache (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func)
128 {
129 	if (!(*var)) {
130 		remoting_lock ();
131 		if (!(*var)) {
132 			GHashTable *cache =
133 				g_hash_table_new (hash_func, equal_func);
134 			mono_memory_barrier ();
135 			*var = cache;
136 		}
137 		remoting_unlock ();
138 	}
139 	return *var;
140 }
141 
142 static GHashTable*
get_cache_full(GHashTable ** var,GHashFunc hash_func,GCompareFunc equal_func,GDestroyNotify key_destroy_func,GDestroyNotify value_destroy_func)143 get_cache_full (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func, GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
144 {
145 	if (!(*var)) {
146 		remoting_lock ();
147 		if (!(*var)) {
148 			GHashTable *cache =
149 				g_hash_table_new_full (hash_func, equal_func, key_destroy_func, value_destroy_func);
150 			mono_memory_barrier ();
151 			*var = cache;
152 		}
153 		remoting_unlock ();
154 	}
155 	return *var;
156 }
157 
158 void
mono_remoting_init(void)159 mono_remoting_init (void)
160 {
161 	mono_os_mutex_init (&remoting_mutex);
162 	remoting_mutex_inited = TRUE;
163 }
164 
165 static void
mono_remoting_marshal_init(void)166 mono_remoting_marshal_init (void)
167 {
168 	MonoClass *klass;
169 
170 	static gboolean module_initialized = FALSE;
171 	static gboolean icalls_registered = FALSE;
172 
173 	if (module_initialized)
174 		return;
175 
176 	byte_array_class = mono_array_class_get (mono_defaults.byte_class, 1);
177 
178 #ifndef DISABLE_JIT
179 	klass = mono_class_get_remoting_services_class ();
180 	method_rs_serialize = mono_class_get_method_from_name (klass, "SerializeCallData", -1);
181 	g_assert (method_rs_serialize);
182 	method_rs_deserialize = mono_class_get_method_from_name (klass, "DeserializeCallData", -1);
183 	g_assert (method_rs_deserialize);
184 	method_rs_serialize_exc = mono_class_get_method_from_name (klass, "SerializeExceptionData", -1);
185 	g_assert (method_rs_serialize_exc);
186 
187 	klass = mono_defaults.real_proxy_class;
188 	method_rs_appdomain_target = mono_class_get_method_from_name (klass, "GetAppDomainTarget", -1);
189 	g_assert (method_rs_appdomain_target);
190 
191 	klass = mono_defaults.exception_class;
192 	method_exc_fixexc = mono_class_get_method_from_name (klass, "FixRemotingException", -1);
193 	g_assert (method_exc_fixexc);
194 
195 	klass = mono_class_get_call_context_class ();
196 	method_set_call_context = mono_class_get_method_from_name (klass, "SetCurrentCallContext", -1);
197 	g_assert (method_set_call_context);
198 
199 	klass = mono_class_get_context_class ();
200 	method_needs_context_sink = mono_class_get_method_from_name (klass, "get_NeedsContextSink", -1);
201 	g_assert (method_needs_context_sink);
202 #endif
203 
204 	mono_loader_lock ();
205 
206 	if (!icalls_registered) {
207 		register_icall (type_from_handle, "type_from_handle", "object ptr", FALSE);
208 		register_icall (mono_marshal_set_domain_by_id, "mono_marshal_set_domain_by_id", "int32 int32 int32", FALSE);
209 		register_icall (mono_marshal_check_domain_image, "mono_marshal_check_domain_image", "int32 int32 ptr", FALSE);
210 		register_icall (ves_icall_mono_marshal_xdomain_copy_value, "ves_icall_mono_marshal_xdomain_copy_value", "object object", FALSE);
211 		register_icall (mono_marshal_xdomain_copy_out_value, "mono_marshal_xdomain_copy_out_value", "void object object", FALSE);
212 		register_icall (mono_remoting_wrapper, "mono_remoting_wrapper", "object ptr ptr", FALSE);
213 		register_icall (mono_remoting_update_exception, "mono_remoting_update_exception", "object object", FALSE);
214 		register_icall (mono_upgrade_remote_class_wrapper, "mono_upgrade_remote_class_wrapper", "void object object", FALSE);
215 
216 #ifndef DISABLE_JIT
217 		register_icall (mono_compile_method_icall, "mono_compile_method_icall", "ptr ptr", FALSE);
218 #endif
219 
220 		register_icall (mono_context_get_icall, "mono_context_get_icall", "object", FALSE);
221 		register_icall (mono_context_set_icall, "mono_context_set_icall", "void object", FALSE);
222 
223 	}
224 
225 	icalls_registered = TRUE;
226 
227 	mono_loader_unlock ();
228 
229 	module_initialized = TRUE;
230 }
231 
232 /* This is an icall, it will return NULL and set pending exception on failure */
233 static MonoReflectionType *
type_from_handle(MonoType * handle)234 type_from_handle (MonoType *handle)
235 {
236 	MonoError error;
237 	MonoReflectionType *ret;
238 	MonoDomain *domain = mono_domain_get ();
239 	MonoClass *klass = mono_class_from_mono_type (handle);
240 
241 	mono_class_init (klass);
242 
243 	ret = mono_type_get_object_checked (domain, handle, &error);
244 	mono_error_set_pending_exception (&error);
245 
246 	return ret;
247 }
248 
249 #ifndef DISABLE_JIT
250 static int
mono_mb_emit_proxy_check(MonoMethodBuilder * mb,int branch_code)251 mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
252 {
253 	int pos;
254 	mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoObject, vtable));
255 	mono_mb_emit_byte (mb, CEE_LDIND_I);
256 	mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoVTable, klass));
257 	mono_mb_emit_byte (mb, CEE_ADD);
258 	mono_mb_emit_byte (mb, CEE_LDIND_I);
259 	mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
260 	mono_mb_emit_byte (mb, CEE_MONO_CLASSCONST);
261 	mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
262 	pos = mono_mb_emit_branch (mb, branch_code);
263 	return pos;
264 }
265 
266 static int
mono_mb_emit_xdomain_check(MonoMethodBuilder * mb,int branch_code)267 mono_mb_emit_xdomain_check (MonoMethodBuilder *mb, int branch_code)
268 {
269 	int pos;
270 	mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp));
271 	mono_mb_emit_byte (mb, CEE_LDIND_REF);
272 	mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoRealProxy, target_domain_id));
273 	mono_mb_emit_byte (mb, CEE_LDIND_I4);
274 	mono_mb_emit_icon (mb, -1);
275 	pos = mono_mb_emit_branch (mb, branch_code);
276 	return pos;
277 }
278 
279 static int
mono_mb_emit_contextbound_check(MonoMethodBuilder * mb,int branch_code)280 mono_mb_emit_contextbound_check (MonoMethodBuilder *mb, int branch_code)
281 {
282 	static int offset = -1;
283 	static guint8 mask;
284 
285 	if (offset < 0)
286 		mono_marshal_find_bitfield_offset (MonoClass, contextbound, &offset, &mask);
287 
288 	mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
289 	mono_mb_emit_byte (mb, CEE_LDIND_REF);
290 	mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
291 	mono_mb_emit_byte (mb, CEE_LDIND_REF);
292 	mono_mb_emit_ldflda (mb, offset);
293 	mono_mb_emit_byte (mb, CEE_LDIND_U1);
294 	mono_mb_emit_icon (mb, mask);
295 	mono_mb_emit_byte (mb, CEE_AND);
296 	mono_mb_emit_icon (mb, 0);
297 	return mono_mb_emit_branch (mb, branch_code);
298 }
299 #endif /* !DISABLE_JIT */
300 
301 static inline MonoMethod*
mono_marshal_remoting_find_in_cache(MonoMethod * method,int wrapper_type)302 mono_marshal_remoting_find_in_cache (MonoMethod *method, int wrapper_type)
303 {
304 	MonoMethod *res = NULL;
305 	MonoRemotingMethods *wrps = NULL;
306 
307 	mono_marshal_lock_internal ();
308 	if (mono_method_get_wrapper_cache (method)->remoting_invoke_cache)
309 		wrps = (MonoRemotingMethods *)g_hash_table_lookup (mono_method_get_wrapper_cache (method)->remoting_invoke_cache, method);
310 
311 	if (wrps) {
312 		switch (wrapper_type) {
313 		case MONO_WRAPPER_REMOTING_INVOKE: res = wrps->invoke; break;
314 		case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK: res = wrps->invoke_with_check; break;
315 		case MONO_WRAPPER_XDOMAIN_INVOKE: res = wrps->xdomain_invoke; break;
316 		case MONO_WRAPPER_XDOMAIN_DISPATCH: res = wrps->xdomain_dispatch; break;
317 		}
318 	}
319 
320 	/* it is important to do the unlock after the load from wrps, since in
321 	 * mono_remoting_mb_create_and_cache () we drop the marshal lock to be able
322 	 * to take the loader lock and some other thread may set the fields.
323 	 */
324 	mono_marshal_unlock_internal ();
325 	return res;
326 }
327 
328 /* Create the method from the builder and place it in the cache */
329 static inline MonoMethod*
mono_remoting_mb_create_and_cache(MonoMethod * key,MonoMethodBuilder * mb,MonoMethodSignature * sig,int max_stack,WrapperInfo * info)330 mono_remoting_mb_create_and_cache (MonoMethod *key, MonoMethodBuilder *mb,
331 								   MonoMethodSignature *sig, int max_stack, WrapperInfo *info)
332 {
333 	MonoMethod **res = NULL;
334 	MonoRemotingMethods *wrps;
335 	GHashTable *cache;
336 
337 	cache = get_cache_full (&mono_method_get_wrapper_cache (key)->remoting_invoke_cache, mono_aligned_addr_hash, NULL, NULL, g_free);
338 
339 	mono_marshal_lock_internal ();
340 	wrps = (MonoRemotingMethods *)g_hash_table_lookup (cache, key);
341 	if (!wrps) {
342 		wrps = g_new0 (MonoRemotingMethods, 1);
343 		g_hash_table_insert (cache, key, wrps);
344 	}
345 
346 	switch (mb->method->wrapper_type) {
347 	case MONO_WRAPPER_REMOTING_INVOKE: res = &wrps->invoke; break;
348 	case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK: res = &wrps->invoke_with_check; break;
349 	case MONO_WRAPPER_XDOMAIN_INVOKE: res = &wrps->xdomain_invoke; break;
350 	case MONO_WRAPPER_XDOMAIN_DISPATCH: res = &wrps->xdomain_dispatch; break;
351 	default: g_assert_not_reached (); break;
352 	}
353 	mono_marshal_unlock_internal ();
354 
355 	if (*res == NULL) {
356 		MonoMethod *newm;
357 		newm = mono_mb_create_method (mb, sig, max_stack);
358 
359 		mono_marshal_lock_internal ();
360 		if (!*res) {
361 			*res = newm;
362 			mono_marshal_set_wrapper_info (*res, info);
363 			mono_marshal_unlock_internal ();
364 		} else {
365 			mono_marshal_unlock_internal ();
366 			mono_free_method (newm);
367 		}
368 	}
369 
370 	return *res;
371 }
372 
373 static MonoObject *
mono_remoting_wrapper(MonoMethod * method,gpointer * params)374 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
375 {
376 	MonoError error;
377 	MonoMethodMessage *msg;
378 	MonoTransparentProxy *this_obj;
379 	MonoObject *res, *exc;
380 	MonoArray *out_args;
381 
382 	this_obj = *((MonoTransparentProxy **)params [0]);
383 
384 	g_assert (this_obj);
385 	g_assert (mono_object_is_transparent_proxy (this_obj));
386 
387 	/* skip the this pointer */
388 	params++;
389 
390 	if (mono_class_is_contextbound (this_obj->remote_class->proxy_class) && this_obj->rp->context == (MonoObject *) mono_context_get ())
391 	{
392 		int i;
393 		MonoMethodSignature *sig = mono_method_signature (method);
394 		int count = sig->param_count;
395 		gpointer* mparams = (gpointer*) alloca(count*sizeof(gpointer));
396 
397 		for (i=0; i<count; i++) {
398 			MonoClass *klass = mono_class_from_mono_type (sig->params [i]);
399 			if (klass->valuetype) {
400 				if (sig->params [i]->byref) {
401 					mparams[i] = *((gpointer *)params [i]);
402 				} else {
403 					/* runtime_invoke expects a boxed instance */
404 					if (mono_class_is_nullable (mono_class_from_mono_type (sig->params [i]))) {
405 						mparams[i] = mono_nullable_box ((guint8 *)params [i], klass, &error);
406 						goto_if_nok (&error, fail);
407 					} else
408 						mparams[i] = params [i];
409 				}
410 			} else {
411 				mparams[i] = *((gpointer**)params [i]);
412 			}
413 		}
414 
415 		res = mono_runtime_invoke_checked (method, method->klass->valuetype? mono_object_unbox ((MonoObject*)this_obj): this_obj, mparams, &error);
416 		goto_if_nok (&error, fail);
417 
418 		return res;
419 	}
420 
421 	msg = mono_method_call_message_new (method, params, NULL, NULL, NULL, &error);
422 	goto_if_nok (&error, fail);
423 
424 	res = mono_remoting_invoke ((MonoObject *)this_obj->rp, msg, &exc, &out_args, &error);
425 	goto_if_nok (&error, fail);
426 
427 	if (exc) {
428 		error_init (&error);
429 		exc = (MonoObject*) mono_remoting_update_exception ((MonoException*)exc);
430 		mono_error_set_exception_instance (&error, (MonoException *)exc);
431 		goto fail;
432 	}
433 
434 	mono_method_return_message_restore (method, params, out_args, &error);
435 	goto_if_nok (&error, fail);
436 
437 	return res;
438 fail:
439 	mono_error_set_pending_exception (&error);
440 	return NULL;
441 }
442 
443 /*
444  * Handles exception transformation at appdomain call boundary.
445  * Note this is called from target appdomain inside xdomain wrapper, but from
446  * source domain in the mono_remoting_wrapper slowpath.
447  */
448 static MonoException *
mono_remoting_update_exception(MonoException * exc)449 mono_remoting_update_exception (MonoException *exc)
450 {
451 	MonoInternalThread *thread;
452 	MonoClass *klass = mono_object_get_class ((MonoObject*)exc);
453 
454 	/* Serialization error can only happen when still in the target appdomain */
455 	if (!(mono_class_get_flags (klass) & TYPE_ATTRIBUTE_SERIALIZABLE)) {
456 		MonoException *ret;
457 		char *aname = mono_stringify_assembly_name (&klass->image->assembly->aname);
458 		char *message = g_strdup_printf ("Type '%s' in Assembly '%s' is not marked as serializable", klass->name, aname);
459 		ret =  mono_get_exception_serialization (message);
460 		g_free (aname);
461 		g_free (message);
462 		return ret;
463 	}
464 
465 	thread = mono_thread_internal_current ();
466 	if (mono_object_get_class ((MonoObject*)exc) == mono_defaults.threadabortexception_class &&
467 			thread->flags & MONO_THREAD_FLAG_APPDOMAIN_ABORT) {
468 		mono_thread_internal_reset_abort (thread);
469 		return mono_get_exception_appdomain_unloaded ();
470 	}
471 
472 	return exc;
473 }
474 
475 /**
476  * mono_marshal_get_remoting_invoke:
477  */
478 MonoMethod *
mono_marshal_get_remoting_invoke(MonoMethod * method)479 mono_marshal_get_remoting_invoke (MonoMethod *method)
480 {
481 	MonoMethodSignature *sig;
482 	MonoMethodBuilder *mb;
483 	MonoMethod *res;
484 	int params_var;
485 	WrapperInfo *info;
486 
487 	g_assert (method);
488 
489 	if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE || method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE)
490 		return method;
491 
492 	/* this seems to be the best plase to put this, as all remoting invokes seem to get filtered through here */
493 #ifndef DISABLE_COM
494 	if (mono_class_is_com_object (method->klass) || method->klass == mono_class_try_get_com_object_class ()) {
495 		MonoVTable *vtable = mono_class_vtable (mono_domain_get (), method->klass);
496 		g_assert (vtable); /*FIXME do proper error handling*/
497 
498 		if (!mono_vtable_is_remote (vtable)) {
499 			return mono_cominterop_get_invoke (method);
500 		}
501 	}
502 #endif
503 
504 	sig = mono_signature_no_pinvoke (method);
505 
506 	/* we cant remote methods without this pointer */
507 	if (!sig->hasthis)
508 		return method;
509 
510 	if ((res = mono_marshal_remoting_find_in_cache (method, MONO_WRAPPER_REMOTING_INVOKE)))
511 		return res;
512 
513 	mono_remoting_marshal_init ();
514 
515 	mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
516 
517 #ifndef DISABLE_JIT
518 	mb->method->save_lmf = 1;
519 
520 	params_var = mono_mb_emit_save_args (mb, sig, TRUE);
521 
522 	mono_mb_emit_ptr (mb, method);
523 	mono_mb_emit_ldloc (mb, params_var);
524 	mono_mb_emit_icall (mb, mono_remoting_wrapper);
525 	// FIXME: this interrupt checkpoint code is a no-op since 'mb'
526 	//  is a MONO_WRAPPER_REMOTING_INVOKE, and
527 	//  mono_thread_interruption_checkpoint_request (FALSE)
528 	//  considers such wrappers "protected" and always returns
529 	//  NULL as if there's no pending interruption.
530 	mono_marshal_emit_thread_interrupt_checkpoint (mb);
531 
532 	if (sig->ret->type == MONO_TYPE_VOID) {
533 		mono_mb_emit_byte (mb, CEE_POP);
534 		mono_mb_emit_byte (mb, CEE_RET);
535 	} else {
536 		 mono_mb_emit_restore_result (mb, sig->ret);
537 	}
538 #endif
539 
540 	info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
541 	info->d.remoting.method = method;
542 	res = mono_remoting_mb_create_and_cache (method, mb, sig, sig->param_count + 16, info);
543 	mono_mb_free (mb);
544 
545 	return res;
546 }
547 
548 /* mono_marshal_xdomain_copy_out_value()
549  * Copies the contents of the src instance into the dst instance. src and dst
550  * must have the same type, and if they are arrays, the same size.
551  *
552  * This is an icall, it may use mono_error_set_pending_exception
553  */
554 static void
mono_marshal_xdomain_copy_out_value(MonoObject * src,MonoObject * dst)555 mono_marshal_xdomain_copy_out_value (MonoObject *src, MonoObject *dst)
556 {
557 	MonoError error;
558 	if (src == NULL || dst == NULL) return;
559 
560 	g_assert (mono_object_class (src) == mono_object_class (dst));
561 
562 	switch (mono_object_class (src)->byval_arg.type) {
563 	case MONO_TYPE_ARRAY:
564 	case MONO_TYPE_SZARRAY: {
565 		int mt = mono_get_xdomain_marshal_type (&(mono_object_class (src)->element_class->byval_arg));
566 		if (mt == MONO_MARSHAL_SERIALIZE) return;
567 		if (mt == MONO_MARSHAL_COPY) {
568 			int i, len = mono_array_length ((MonoArray *)dst);
569 			for (i = 0; i < len; i++) {
570 				MonoObject *item = (MonoObject *)mono_array_get ((MonoArray *)src, gpointer, i);
571 				MonoObject *item_copy = mono_marshal_xdomain_copy_value (item, &error);
572 				if (mono_error_set_pending_exception (&error))
573 					return;
574 				mono_array_setref ((MonoArray *)dst, i, item_copy);
575 			}
576 		} else {
577 			mono_array_full_copy ((MonoArray *)src, (MonoArray *)dst);
578 		}
579 		return;
580 	}
581 	default:
582 		break;
583 	}
584 
585 }
586 
587 
588 #if !defined (DISABLE_JIT)
589 static void
mono_marshal_emit_xdomain_copy_value(MonoMethodBuilder * mb,MonoClass * pclass)590 mono_marshal_emit_xdomain_copy_value (MonoMethodBuilder *mb, MonoClass *pclass)
591 {
592 	mono_mb_emit_icall (mb, ves_icall_mono_marshal_xdomain_copy_value);
593 	mono_mb_emit_op (mb, CEE_CASTCLASS, pclass);
594 }
595 
596 static void
mono_marshal_emit_xdomain_copy_out_value(MonoMethodBuilder * mb,MonoClass * pclass)597 mono_marshal_emit_xdomain_copy_out_value (MonoMethodBuilder *mb, MonoClass *pclass)
598 {
599 	mono_mb_emit_icall (mb, mono_marshal_xdomain_copy_out_value);
600 }
601 #endif
602 
603 /* mono_marshal_supports_fast_xdomain()
604  * Returns TRUE if the method can use the fast xdomain wrapper.
605  */
606 static gboolean
mono_marshal_supports_fast_xdomain(MonoMethod * method)607 mono_marshal_supports_fast_xdomain (MonoMethod *method)
608 {
609 	return !mono_class_is_contextbound (method->klass) &&
610 		   !((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && (strcmp (".ctor", method->name) == 0));
611 }
612 
613 static gint32
mono_marshal_set_domain_by_id(gint32 id,MonoBoolean push)614 mono_marshal_set_domain_by_id (gint32 id, MonoBoolean push)
615 {
616 	MonoDomain *current_domain = mono_domain_get ();
617 	MonoDomain *domain = mono_domain_get_by_id (id);
618 
619 	if (!domain || !mono_domain_set (domain, FALSE)) {
620 		mono_set_pending_exception (mono_get_exception_appdomain_unloaded ());
621 		return 0;
622 	}
623 
624 	if (push)
625 		mono_thread_push_appdomain_ref (domain);
626 	else
627 		mono_thread_pop_appdomain_ref ();
628 
629 	return current_domain->domain_id;
630 }
631 
632 #if !defined (DISABLE_JIT)
633 static void
mono_marshal_emit_switch_domain(MonoMethodBuilder * mb)634 mono_marshal_emit_switch_domain (MonoMethodBuilder *mb)
635 {
636 	mono_mb_emit_icall (mb, mono_marshal_set_domain_by_id);
637 }
638 
639 gpointer
mono_compile_method_icall(MonoMethod * method)640 mono_compile_method_icall (MonoMethod *method)
641 {
642 	MonoError error;
643 	gpointer result = mono_compile_method_checked (method, &error);
644 	mono_error_set_pending_exception (&error);
645 	return result;
646 }
647 
648 /* mono_marshal_emit_load_domain_method ()
649  * Loads into the stack a pointer to the code of the provided method for
650  * the current domain.
651  */
652 static void
mono_marshal_emit_load_domain_method(MonoMethodBuilder * mb,MonoMethod * method)653 mono_marshal_emit_load_domain_method (MonoMethodBuilder *mb, MonoMethod *method)
654 {
655 	/* We need a pointer to the method for the running domain (not the domain
656 	 * that compiles the method).
657 	 */
658 	mono_mb_emit_ptr (mb, method);
659 	mono_mb_emit_icall (mb, mono_compile_method_icall);
660 }
661 #endif
662 
663 /* mono_marshal_check_domain_image ()
664  * Returns TRUE if the image is loaded in the specified
665  * application domain.
666  */
667 static gboolean
mono_marshal_check_domain_image(gint32 domain_id,MonoImage * image)668 mono_marshal_check_domain_image (gint32 domain_id, MonoImage *image)
669 {
670 	MonoAssembly* ass;
671 	GSList *tmp;
672 
673 	MonoDomain *domain = mono_domain_get_by_id (domain_id);
674 	if (!domain)
675 		return FALSE;
676 
677 	mono_domain_assemblies_lock (domain);
678 	for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
679 		ass = (MonoAssembly *)tmp->data;
680 		if (ass->image == image)
681 			break;
682 	}
683 	mono_domain_assemblies_unlock (domain);
684 
685 	return tmp != NULL;
686 }
687 
688 /* mono_marshal_get_xappdomain_dispatch ()
689  * Generates a method that dispatches a method call from another domain into
690  * the current domain.
691  */
692 static MonoMethod *
mono_marshal_get_xappdomain_dispatch(MonoMethod * method,int * marshal_types,int complex_count,int complex_out_count,int ret_marshal_type)693 mono_marshal_get_xappdomain_dispatch (MonoMethod *method, int *marshal_types, int complex_count, int complex_out_count, int ret_marshal_type)
694 {
695 	MonoMethodSignature *sig, *csig;
696 	MonoMethodBuilder *mb;
697 	MonoMethod *res;
698 	int i, j, param_index, copy_locals_base;
699 	MonoClass *ret_class = NULL;
700 	int loc_array=0, loc_return=0, loc_serialized_exc=0;
701 	MonoExceptionClause *main_clause;
702 	int pos, pos_leave;
703 	gboolean copy_return;
704 	WrapperInfo *info;
705 
706 	if ((res = mono_marshal_remoting_find_in_cache (method, MONO_WRAPPER_XDOMAIN_DISPATCH)))
707 		return res;
708 
709 	sig = mono_method_signature (method);
710 	copy_return = (sig->ret->type != MONO_TYPE_VOID && ret_marshal_type != MONO_MARSHAL_SERIALIZE);
711 
712 	j = 0;
713 	csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3 + sig->param_count - complex_count);
714 	csig->params [j++] = &mono_defaults.object_class->byval_arg;
715 	csig->params [j++] = &byte_array_class->this_arg;
716 	csig->params [j++] = &byte_array_class->this_arg;
717 	for (i = 0; i < sig->param_count; i++) {
718 		if (marshal_types [i] != MONO_MARSHAL_SERIALIZE)
719 			csig->params [j++] = sig->params [i];
720 	}
721 	if (copy_return)
722 		csig->ret = sig->ret;
723 	else
724 		csig->ret = &mono_defaults.void_class->byval_arg;
725 	csig->pinvoke = 1;
726 	csig->hasthis = FALSE;
727 
728 	mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_XDOMAIN_DISPATCH);
729 	mb->method->save_lmf = 1;
730 
731 #ifndef DISABLE_JIT
732 	/* Locals */
733 
734 	loc_serialized_exc = mono_mb_add_local (mb, &byte_array_class->byval_arg);
735 	if (complex_count > 0)
736 		loc_array = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
737 	if (sig->ret->type != MONO_TYPE_VOID) {
738 		loc_return = mono_mb_add_local (mb, sig->ret);
739 		ret_class = mono_class_from_mono_type (sig->ret);
740 	}
741 
742 	/* try */
743 
744 	main_clause = (MonoExceptionClause *)mono_image_alloc0 (method->klass->image, sizeof (MonoExceptionClause));
745 	main_clause->try_offset = mono_mb_get_label (mb);
746 
747 	/* Clean the call context */
748 
749 	mono_mb_emit_byte (mb, CEE_LDNULL);
750 	mono_mb_emit_managed_call (mb, method_set_call_context, NULL);
751 	mono_mb_emit_byte (mb, CEE_POP);
752 
753 	/* Deserialize call data */
754 
755 	mono_mb_emit_ldarg (mb, 1);
756 	mono_mb_emit_byte (mb, CEE_LDIND_REF);
757 	mono_mb_emit_byte (mb, CEE_DUP);
758 	pos = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
759 
760 	mono_marshal_emit_xdomain_copy_value (mb, byte_array_class);
761 	mono_mb_emit_managed_call (mb, method_rs_deserialize, NULL);
762 
763 	if (complex_count > 0)
764 		mono_mb_emit_stloc (mb, loc_array);
765 	else
766 		mono_mb_emit_byte (mb, CEE_POP);
767 
768 	mono_mb_patch_short_branch (mb, pos);
769 
770 	/* Get the target object */
771 
772 	mono_mb_emit_ldarg (mb, 0);
773 	mono_mb_emit_managed_call (mb, method_rs_appdomain_target, NULL);
774 
775 	/* Load the arguments */
776 
777 	copy_locals_base = mb->locals;
778 	param_index = 3;	// Index of the first non-serialized parameter of this wrapper
779 	j = 0;
780 	for (i = 0; i < sig->param_count; i++) {
781 		MonoType *pt = sig->params [i];
782 		MonoClass *pclass = mono_class_from_mono_type (pt);
783 		switch (marshal_types [i]) {
784 		case MONO_MARSHAL_SERIALIZE: {
785 			/* take the value from the serialized array */
786 			mono_mb_emit_ldloc (mb, loc_array);
787 			mono_mb_emit_icon (mb, j++);
788 			if (pt->byref) {
789 				if (pclass->valuetype) {
790 					mono_mb_emit_byte (mb, CEE_LDELEM_REF);
791 					mono_mb_emit_op (mb, CEE_UNBOX, pclass);
792 				} else {
793 					mono_mb_emit_op (mb, CEE_LDELEMA, pclass);
794 				}
795 			} else {
796 				if (pclass->valuetype) {
797 					mono_mb_emit_byte (mb, CEE_LDELEM_REF);
798 					mono_mb_emit_op (mb, CEE_UNBOX, pclass);
799 					mono_mb_emit_op (mb, CEE_LDOBJ, pclass);
800 				} else {
801 					mono_mb_emit_byte (mb, CEE_LDELEM_REF);
802 					if (pclass != mono_defaults.object_class) {
803 						mono_mb_emit_op (mb, CEE_CASTCLASS, pclass);
804 					}
805 				}
806 			}
807 			break;
808 		}
809 		case MONO_MARSHAL_COPY_OUT: {
810 			/* Keep a local copy of the value since we need to copy it back after the call */
811 			int copy_local = mono_mb_add_local (mb, &(pclass->byval_arg));
812 			mono_mb_emit_ldarg (mb, param_index++);
813 			mono_marshal_emit_xdomain_copy_value (mb, pclass);
814 			mono_mb_emit_byte (mb, CEE_DUP);
815 			mono_mb_emit_stloc (mb, copy_local);
816 			break;
817 		}
818 		case MONO_MARSHAL_COPY: {
819 			mono_mb_emit_ldarg (mb, param_index);
820 			if (pt->byref) {
821 				mono_mb_emit_byte (mb, CEE_DUP);
822 				mono_mb_emit_byte (mb, CEE_DUP);
823 				mono_mb_emit_byte (mb, CEE_LDIND_REF);
824 				mono_marshal_emit_xdomain_copy_value (mb, pclass);
825 				mono_mb_emit_byte (mb, CEE_STIND_REF);
826 			} else {
827 				mono_marshal_emit_xdomain_copy_value (mb, pclass);
828 			}
829 			param_index++;
830 			break;
831 		}
832 		case MONO_MARSHAL_NONE:
833 			mono_mb_emit_ldarg (mb, param_index++);
834 			break;
835 		}
836 	}
837 
838 	/* Make the call to the real object */
839 
840 	mono_marshal_emit_thread_force_interrupt_checkpoint (mb);
841 
842 	mono_mb_emit_op (mb, CEE_CALLVIRT, method);
843 
844 	if (sig->ret->type != MONO_TYPE_VOID)
845 		mono_mb_emit_stloc (mb, loc_return);
846 
847 	/* copy back MONO_MARSHAL_COPY_OUT parameters */
848 
849 	j = 0;
850 	param_index = 3;
851 	for (i = 0; i < sig->param_count; i++) {
852 		if (marshal_types [i] == MONO_MARSHAL_SERIALIZE) continue;
853 		if (marshal_types [i] == MONO_MARSHAL_COPY_OUT) {
854 			mono_mb_emit_ldloc (mb, copy_locals_base + (j++));
855 			mono_mb_emit_ldarg (mb, param_index);
856 			mono_marshal_emit_xdomain_copy_out_value (mb, mono_class_from_mono_type (sig->params [i]));
857 		}
858 		param_index++;
859 	}
860 
861 	/* Serialize the return values */
862 
863 	if (complex_out_count > 0) {
864 		/* Reset parameters in the array that don't need to be serialized back */
865 		j = 0;
866 		for (i = 0; i < sig->param_count; i++) {
867 			if (marshal_types[i] != MONO_MARSHAL_SERIALIZE) continue;
868 			if (!sig->params [i]->byref) {
869 				mono_mb_emit_ldloc (mb, loc_array);
870 				mono_mb_emit_icon (mb, j);
871 				mono_mb_emit_byte (mb, CEE_LDNULL);
872 				mono_mb_emit_byte (mb, CEE_STELEM_REF);
873 			}
874 			j++;
875 		}
876 
877 		/* Add the return value to the array */
878 
879 		if (ret_marshal_type == MONO_MARSHAL_SERIALIZE) {
880 			mono_mb_emit_ldloc (mb, loc_array);
881 			mono_mb_emit_icon (mb, complex_count);	/* The array has an additional slot to hold the ret value */
882 			mono_mb_emit_ldloc (mb, loc_return);
883 
884 			g_assert (ret_class); /*FIXME properly fail here*/
885 			if (ret_class->valuetype) {
886 				mono_mb_emit_op (mb, CEE_BOX, ret_class);
887 			}
888 			mono_mb_emit_byte (mb, CEE_STELEM_REF);
889 		}
890 
891 		/* Serialize */
892 
893 		mono_mb_emit_ldarg (mb, 1);
894 		mono_mb_emit_ldloc (mb, loc_array);
895 		mono_mb_emit_managed_call (mb, method_rs_serialize, NULL);
896 		mono_mb_emit_byte (mb, CEE_STIND_REF);
897 	} else if (ret_marshal_type == MONO_MARSHAL_SERIALIZE) {
898 		mono_mb_emit_ldarg (mb, 1);
899 		mono_mb_emit_ldloc (mb, loc_return);
900 		if (ret_class->valuetype) {
901 			mono_mb_emit_op (mb, CEE_BOX, ret_class);
902 		}
903 		mono_mb_emit_managed_call (mb, method_rs_serialize, NULL);
904 		mono_mb_emit_byte (mb, CEE_STIND_REF);
905 	} else {
906 		mono_mb_emit_ldarg (mb, 1);
907 		mono_mb_emit_byte (mb, CEE_LDNULL);
908 		mono_mb_emit_managed_call (mb, method_rs_serialize, NULL);
909 		mono_mb_emit_byte (mb, CEE_STIND_REF);
910 	}
911 
912 	mono_mb_emit_ldarg (mb, 2);
913 	mono_mb_emit_byte (mb, CEE_LDNULL);
914 	mono_mb_emit_byte (mb, CEE_STIND_REF);
915 	pos_leave = mono_mb_emit_branch (mb, CEE_LEAVE);
916 
917 	/* Main exception catch */
918 	main_clause->flags = MONO_EXCEPTION_CLAUSE_NONE;
919 	main_clause->try_len = mono_mb_get_pos (mb) - main_clause->try_offset;
920 	main_clause->data.catch_class = mono_defaults.object_class;
921 
922 	/* handler code */
923 	main_clause->handler_offset = mono_mb_get_label (mb);
924 
925 	mono_mb_emit_icall (mb, mono_remoting_update_exception);
926 	mono_mb_emit_op (mb, CEE_CASTCLASS, mono_defaults.exception_class);
927 	mono_mb_emit_managed_call (mb, method_rs_serialize_exc, NULL);
928 	mono_mb_emit_stloc (mb, loc_serialized_exc);
929 	mono_mb_emit_ldarg (mb, 2);
930 	mono_mb_emit_ldloc (mb, loc_serialized_exc);
931 	mono_mb_emit_byte (mb, CEE_STIND_REF);
932 	mono_mb_emit_branch (mb, CEE_LEAVE);
933 
934 	main_clause->handler_len = mono_mb_get_pos (mb) - main_clause->handler_offset;
935 	/* end catch */
936 	mono_mb_patch_branch (mb, pos_leave);
937 
938 	if (copy_return)
939 		mono_mb_emit_ldloc (mb, loc_return);
940 
941 	mono_mb_emit_byte (mb, CEE_RET);
942 
943 	mono_mb_set_clauses (mb, 1, main_clause);
944 #endif
945 
946 	info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
947 	info->d.remoting.method = method;
948 	res = mono_remoting_mb_create_and_cache (method, mb, csig, csig->param_count + 16, info);
949 	mono_mb_free (mb);
950 
951 	return res;
952 }
953 
954 /**
955  * mono_marshal_get_xappdomain_invoke:
956  * Generates a fast remoting wrapper for cross app domain calls.
957  */
958 MonoMethod *
mono_marshal_get_xappdomain_invoke(MonoMethod * method)959 mono_marshal_get_xappdomain_invoke (MonoMethod *method)
960 {
961 	MonoMethodSignature *sig;
962 	MonoMethodBuilder *mb;
963 	MonoMethod *res;
964 	int i, j, complex_count, complex_out_count, copy_locals_base;
965 	int *marshal_types;
966 	MonoClass *ret_class = NULL;
967 	MonoMethod *xdomain_method;
968 	int ret_marshal_type = MONO_MARSHAL_NONE;
969 	int loc_array=0, loc_serialized_data=-1, loc_real_proxy;
970 	int loc_old_domainid, loc_domainid, loc_return=0, loc_serialized_exc=0, loc_context;
971 	int pos, pos_dispatch, pos_noex;
972 	gboolean copy_return = FALSE;
973 	WrapperInfo *info;
974 
975 	g_assert (method);
976 
977 	if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE || method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE)
978 		return method;
979 
980 	/* we cant remote methods without this pointer */
981 	if (!mono_method_signature (method)->hasthis)
982 		return method;
983 
984 	mono_remoting_marshal_init ();
985 
986 	if (!mono_marshal_supports_fast_xdomain (method))
987 		return mono_marshal_get_remoting_invoke (method);
988 
989 	if ((res = mono_marshal_remoting_find_in_cache (method, MONO_WRAPPER_XDOMAIN_INVOKE)))
990 		return res;
991 
992 	sig = mono_signature_no_pinvoke (method);
993 
994 	mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_XDOMAIN_INVOKE);
995 	mb->method->save_lmf = 1;
996 
997 	/* Count the number of parameters that need to be serialized */
998 
999 	marshal_types = (int *)alloca (sizeof (int) * sig->param_count);
1000 	complex_count = complex_out_count = 0;
1001 	for (i = 0; i < sig->param_count; i++) {
1002 		MonoType *ptype = sig->params[i];
1003 		int mt = mono_get_xdomain_marshal_type (ptype);
1004 
1005 		/* If the [Out] attribute is applied to a parameter that can be internally copied,
1006 		 * the copy will be made by reusing the original object instance
1007 		 */
1008 		if ((ptype->attrs & PARAM_ATTRIBUTE_OUT) != 0 && mt == MONO_MARSHAL_COPY && !ptype->byref)
1009 			mt = MONO_MARSHAL_COPY_OUT;
1010 		else if (mt == MONO_MARSHAL_SERIALIZE) {
1011 			complex_count++;
1012 			if (ptype->byref) complex_out_count++;
1013 		}
1014 		marshal_types [i] = mt;
1015 	}
1016 
1017 	if (sig->ret->type != MONO_TYPE_VOID) {
1018 		ret_marshal_type = mono_get_xdomain_marshal_type (sig->ret);
1019 		ret_class = mono_class_from_mono_type (sig->ret);
1020 		copy_return = ret_marshal_type != MONO_MARSHAL_SERIALIZE;
1021 	}
1022 
1023 	/* Locals */
1024 
1025 #ifndef DISABLE_JIT
1026 	if (complex_count > 0)
1027 		loc_array = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1028 	loc_serialized_data = mono_mb_add_local (mb, &byte_array_class->byval_arg);
1029 	loc_real_proxy = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1030 	if (copy_return)
1031 		loc_return = mono_mb_add_local (mb, sig->ret);
1032 	loc_old_domainid = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg);
1033 	loc_domainid = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg);
1034 	loc_serialized_exc = mono_mb_add_local (mb, &byte_array_class->byval_arg);
1035 	loc_context = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1036 
1037 	/* Save thread domain data */
1038 
1039 	mono_mb_emit_icall (mb, mono_context_get_icall);
1040 	mono_mb_emit_byte (mb, CEE_DUP);
1041 	mono_mb_emit_stloc (mb, loc_context);
1042 
1043 	/* If the thread is not running in the default context, it needs to go
1044 	 * through the whole remoting sink, since the context is going to change
1045 	 */
1046 	mono_mb_emit_managed_call (mb, method_needs_context_sink, NULL);
1047 	pos = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S);
1048 
1049 	/* Another case in which the fast path can't be used: when the target domain
1050 	 * has a different image for the same assembly.
1051 	 */
1052 
1053 	/* Get the target domain id */
1054 
1055 	mono_mb_emit_ldarg (mb, 0);
1056 	mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp));
1057 	mono_mb_emit_byte (mb, CEE_LDIND_REF);
1058 	mono_mb_emit_byte (mb, CEE_DUP);
1059 	mono_mb_emit_stloc (mb, loc_real_proxy);
1060 
1061 	mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoRealProxy, target_domain_id));
1062 	mono_mb_emit_byte (mb, CEE_LDIND_I4);
1063 	mono_mb_emit_stloc (mb, loc_domainid);
1064 
1065 	/* Check if the target domain has the same image for the required assembly */
1066 
1067 	mono_mb_emit_ldloc (mb, loc_domainid);
1068 	mono_mb_emit_ptr (mb, method->klass->image);
1069 	mono_mb_emit_icall (mb, mono_marshal_check_domain_image);
1070 	pos_dispatch = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S);
1071 
1072 	/* Use the whole remoting sink to dispatch this message */
1073 
1074 	mono_mb_patch_short_branch (mb, pos);
1075 
1076 	mono_mb_emit_ldarg (mb, 0);
1077 	for (i = 0; i < sig->param_count; i++)
1078 		mono_mb_emit_ldarg (mb, i + 1);
1079 
1080 	mono_mb_emit_managed_call (mb, mono_marshal_get_remoting_invoke (method), NULL);
1081 	mono_mb_emit_byte (mb, CEE_RET);
1082 	mono_mb_patch_short_branch (mb, pos_dispatch);
1083 
1084 	/* Create the array that will hold the parameters to be serialized */
1085 
1086 	if (complex_count > 0) {
1087 		mono_mb_emit_icon (mb, (ret_marshal_type == MONO_MARSHAL_SERIALIZE && complex_out_count > 0) ? complex_count + 1 : complex_count);	/* +1 for the return type */
1088 		mono_mb_emit_op (mb, CEE_NEWARR, mono_defaults.object_class);
1089 
1090 		j = 0;
1091 		for (i = 0; i < sig->param_count; i++) {
1092 			MonoClass *pclass;
1093 			if (marshal_types [i] != MONO_MARSHAL_SERIALIZE) continue;
1094 			pclass = mono_class_from_mono_type (sig->params[i]);
1095 			mono_mb_emit_byte (mb, CEE_DUP);
1096 			mono_mb_emit_icon (mb, j);
1097 			mono_mb_emit_ldarg (mb, i + 1);		/* 0=this */
1098 			if (sig->params[i]->byref) {
1099 				if (pclass->valuetype)
1100 					mono_mb_emit_op (mb, CEE_LDOBJ, pclass);
1101 				else
1102 					mono_mb_emit_byte (mb, CEE_LDIND_REF);
1103 			}
1104 			if (pclass->valuetype)
1105 				mono_mb_emit_op (mb, CEE_BOX, pclass);
1106 			mono_mb_emit_byte (mb, CEE_STELEM_REF);
1107 			j++;
1108 		}
1109 		mono_mb_emit_stloc (mb, loc_array);
1110 
1111 		/* Serialize parameters */
1112 
1113 		mono_mb_emit_ldloc (mb, loc_array);
1114 		mono_mb_emit_managed_call (mb, method_rs_serialize, NULL);
1115 		mono_mb_emit_stloc (mb, loc_serialized_data);
1116 	} else {
1117 		mono_mb_emit_byte (mb, CEE_LDNULL);
1118 		mono_mb_emit_managed_call (mb, method_rs_serialize, NULL);
1119 		mono_mb_emit_stloc (mb, loc_serialized_data);
1120 	}
1121 
1122 	/* switch domain */
1123 
1124 	mono_mb_emit_ldloc (mb, loc_domainid);
1125 	mono_mb_emit_byte (mb, CEE_LDC_I4_1);
1126 	mono_marshal_emit_switch_domain (mb);
1127 	mono_mb_emit_stloc (mb, loc_old_domainid);
1128 
1129 	/* Load the arguments */
1130 
1131 	mono_mb_emit_ldloc (mb, loc_real_proxy);
1132 	mono_mb_emit_ldloc_addr (mb, loc_serialized_data);
1133 	mono_mb_emit_ldloc_addr (mb, loc_serialized_exc);
1134 
1135 	copy_locals_base = mb->locals;
1136 	for (i = 0; i < sig->param_count; i++) {
1137 		switch (marshal_types [i]) {
1138 		case MONO_MARSHAL_SERIALIZE:
1139 			continue;
1140 		case MONO_MARSHAL_COPY: {
1141 			mono_mb_emit_ldarg (mb, i+1);
1142 			if (sig->params [i]->byref) {
1143 				/* make a local copy of the byref parameter. The real parameter
1144 				 * will be updated after the xdomain call
1145 				 */
1146 				MonoClass *pclass = mono_class_from_mono_type (sig->params [i]);
1147 				int copy_local = mono_mb_add_local (mb, &(pclass->byval_arg));
1148 				mono_mb_emit_byte (mb, CEE_LDIND_REF);
1149 				mono_mb_emit_stloc (mb, copy_local);
1150 				mono_mb_emit_ldloc_addr (mb, copy_local);
1151 			}
1152 			break;
1153 		}
1154 		case MONO_MARSHAL_COPY_OUT:
1155 		case MONO_MARSHAL_NONE:
1156 			mono_mb_emit_ldarg (mb, i+1);
1157 			break;
1158 		}
1159 	}
1160 
1161 	/* Make the call to the invoke wrapper in the target domain */
1162 
1163 	xdomain_method = mono_marshal_get_xappdomain_dispatch (method, marshal_types, complex_count, complex_out_count, ret_marshal_type);
1164 	mono_marshal_emit_load_domain_method (mb, xdomain_method);
1165 	mono_mb_emit_calli (mb, mono_method_signature (xdomain_method));
1166 
1167 	if (copy_return)
1168 		mono_mb_emit_stloc (mb, loc_return);
1169 
1170 	/* Switch domain */
1171 
1172 	mono_mb_emit_ldloc (mb, loc_old_domainid);
1173 	mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1174 	mono_marshal_emit_switch_domain (mb);
1175 	mono_mb_emit_byte (mb, CEE_POP);
1176 
1177 	/* Restore thread domain data */
1178 
1179 	mono_mb_emit_ldloc (mb, loc_context);
1180 	mono_mb_emit_icall (mb, mono_context_set_icall);
1181 
1182 	/* if (loc_serialized_exc != null) ... */
1183 
1184 	mono_mb_emit_ldloc (mb, loc_serialized_exc);
1185 	pos_noex = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
1186 
1187 	mono_mb_emit_ldloc (mb, loc_serialized_exc);
1188 	mono_marshal_emit_xdomain_copy_value (mb, byte_array_class);
1189 	mono_mb_emit_managed_call (mb, method_rs_deserialize, NULL);
1190 	mono_mb_emit_op (mb, CEE_CASTCLASS, mono_defaults.exception_class);
1191 	mono_mb_emit_managed_call (mb, method_exc_fixexc, NULL);
1192 	mono_mb_emit_byte (mb, CEE_THROW);
1193 	mono_mb_patch_short_branch (mb, pos_noex);
1194 
1195 	/* copy back non-serialized output parameters */
1196 
1197 	j = 0;
1198 	for (i = 0; i < sig->param_count; i++) {
1199 		if (!sig->params [i]->byref || marshal_types [i] != MONO_MARSHAL_COPY) continue;
1200 		mono_mb_emit_ldarg (mb, i + 1);
1201 		mono_mb_emit_ldloc (mb, copy_locals_base + (j++));
1202 		mono_marshal_emit_xdomain_copy_value (mb, mono_class_from_mono_type (sig->params [i]));
1203 		mono_mb_emit_byte (mb, CEE_STIND_REF);
1204 	}
1205 
1206 	/* Deserialize out parameters */
1207 
1208 	if (complex_out_count > 0) {
1209 		mono_mb_emit_ldloc (mb, loc_serialized_data);
1210 		mono_marshal_emit_xdomain_copy_value (mb, byte_array_class);
1211 		mono_mb_emit_managed_call (mb, method_rs_deserialize, NULL);
1212 		mono_mb_emit_stloc (mb, loc_array);
1213 
1214 		/* Copy back output parameters and return type */
1215 
1216 		j = 0;
1217 		for (i = 0; i < sig->param_count; i++) {
1218 			if (marshal_types [i] != MONO_MARSHAL_SERIALIZE) continue;
1219 			if (sig->params[i]->byref) {
1220 				MonoClass *pclass = mono_class_from_mono_type (sig->params [i]);
1221 				mono_mb_emit_ldarg (mb, i + 1);
1222 				mono_mb_emit_ldloc (mb, loc_array);
1223 				mono_mb_emit_icon (mb, j);
1224 				mono_mb_emit_byte (mb, CEE_LDELEM_REF);
1225 				if (pclass->valuetype) {
1226 					mono_mb_emit_op (mb, CEE_UNBOX, pclass);
1227 					mono_mb_emit_op (mb, CEE_LDOBJ, pclass);
1228 					mono_mb_emit_op (mb, CEE_STOBJ, pclass);
1229 				} else {
1230 					if (pclass != mono_defaults.object_class)
1231 						mono_mb_emit_op (mb, CEE_CASTCLASS, pclass);
1232 					mono_mb_emit_byte (mb, CEE_STIND_REF);
1233 				}
1234 			}
1235 			j++;
1236 		}
1237 
1238 		if (ret_marshal_type == MONO_MARSHAL_SERIALIZE) {
1239 			mono_mb_emit_ldloc (mb, loc_array);
1240 			mono_mb_emit_icon (mb, complex_count);
1241 			mono_mb_emit_byte (mb, CEE_LDELEM_REF);
1242 			if (ret_class->valuetype) {
1243 				mono_mb_emit_op (mb, CEE_UNBOX, ret_class);
1244 				mono_mb_emit_op (mb, CEE_LDOBJ, ret_class);
1245 			}
1246 		}
1247 	} else if (ret_marshal_type == MONO_MARSHAL_SERIALIZE) {
1248 		mono_mb_emit_ldloc (mb, loc_serialized_data);
1249 		mono_marshal_emit_xdomain_copy_value (mb, byte_array_class);
1250 		mono_mb_emit_managed_call (mb, method_rs_deserialize, NULL);
1251 		if (ret_class->valuetype) {
1252 			mono_mb_emit_op (mb, CEE_UNBOX, ret_class);
1253 			mono_mb_emit_op (mb, CEE_LDOBJ, ret_class);
1254 		} else if (ret_class != mono_defaults.object_class) {
1255 			mono_mb_emit_op (mb, CEE_CASTCLASS, ret_class);
1256 		}
1257 	} else {
1258 		mono_mb_emit_ldloc (mb, loc_serialized_data);
1259 		mono_mb_emit_byte (mb, CEE_DUP);
1260 		pos = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
1261 		mono_marshal_emit_xdomain_copy_value (mb, byte_array_class);
1262 
1263 		mono_mb_patch_short_branch (mb, pos);
1264 		mono_mb_emit_managed_call (mb, method_rs_deserialize, NULL);
1265 		mono_mb_emit_byte (mb, CEE_POP);
1266 	}
1267 
1268 	if (copy_return) {
1269 		mono_mb_emit_ldloc (mb, loc_return);
1270 		if (ret_marshal_type == MONO_MARSHAL_COPY)
1271 			mono_marshal_emit_xdomain_copy_value (mb, ret_class);
1272 	}
1273 
1274 	mono_mb_emit_byte (mb, CEE_RET);
1275 #endif /* DISABLE_JIT */
1276 
1277 	info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
1278 	info->d.remoting.method = method;
1279 	res = mono_remoting_mb_create_and_cache (method, mb, sig, sig->param_count + 16, info);
1280 	mono_mb_free (mb);
1281 
1282 	return res;
1283 }
1284 
1285 /**
1286  * mono_marshal_get_remoting_invoke_for_target:
1287  */
1288 MonoMethod *
mono_marshal_get_remoting_invoke_for_target(MonoMethod * method,MonoRemotingTarget target_type)1289 mono_marshal_get_remoting_invoke_for_target (MonoMethod *method, MonoRemotingTarget target_type)
1290 {
1291 	if (target_type == MONO_REMOTING_TARGET_APPDOMAIN) {
1292 		return mono_marshal_get_xappdomain_invoke (method);
1293 	} else if (target_type == MONO_REMOTING_TARGET_COMINTEROP) {
1294 #ifndef DISABLE_COM
1295 		return mono_cominterop_get_invoke (method);
1296 #else
1297 		g_assert_not_reached ();
1298 #endif
1299 	} else {
1300 		return mono_marshal_get_remoting_invoke (method);
1301 	}
1302 	/* Not erached */
1303 	return NULL;
1304 }
1305 
1306 G_GNUC_UNUSED static gpointer
mono_marshal_load_remoting_wrapper(MonoRealProxy * rp,MonoMethod * method)1307 mono_marshal_load_remoting_wrapper (MonoRealProxy *rp, MonoMethod *method)
1308 {
1309 	MonoError error;
1310 	MonoMethod *marshal_method = NULL;
1311 	if (rp->target_domain_id != -1)
1312 		marshal_method = mono_marshal_get_xappdomain_invoke (method);
1313 	else
1314 		marshal_method = mono_marshal_get_remoting_invoke (method);
1315 	gpointer compiled_ptr = mono_compile_method_checked (marshal_method, &error);
1316 	mono_error_assert_ok (&error);
1317 	return compiled_ptr;
1318 }
1319 
1320 /**
1321  * mono_marshal_get_remoting_invoke_with_check:
1322  */
1323 MonoMethod *
mono_marshal_get_remoting_invoke_with_check(MonoMethod * method)1324 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1325 {
1326 	MonoMethodSignature *sig;
1327 	MonoMethodBuilder *mb;
1328 	MonoMethod *res, *native;
1329 	WrapperInfo *info;
1330 	int i, pos, pos_rem;
1331 
1332 	g_assert (method);
1333 
1334 	if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1335 		return method;
1336 
1337 	/* we cant remote methods without this pointer */
1338 	g_assert (mono_method_signature (method)->hasthis);
1339 
1340 	if ((res = mono_marshal_remoting_find_in_cache (method, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)))
1341 		return res;
1342 
1343 	sig = mono_signature_no_pinvoke (method);
1344 
1345 	mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1346 
1347 #ifndef DISABLE_JIT
1348 	for (i = 0; i <= sig->param_count; i++)
1349 		mono_mb_emit_ldarg (mb, i);
1350 
1351 	mono_mb_emit_ldarg (mb, 0);
1352 	pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1353 
1354 	if (mono_marshal_supports_fast_xdomain (method)) {
1355 		mono_mb_emit_ldarg (mb, 0);
1356 		pos_rem = mono_mb_emit_xdomain_check (mb, CEE_BEQ);
1357 
1358 		/* wrapper for cross app domain calls */
1359 		native = mono_marshal_get_xappdomain_invoke (method);
1360 		mono_mb_emit_managed_call (mb, native, mono_method_signature (native));
1361 		mono_mb_emit_byte (mb, CEE_RET);
1362 
1363 		mono_mb_patch_branch (mb, pos_rem);
1364 	}
1365 	/* wrapper for normal remote calls */
1366 	native = mono_marshal_get_remoting_invoke (method);
1367 	mono_mb_emit_managed_call (mb, native, mono_method_signature (native));
1368 	mono_mb_emit_byte (mb, CEE_RET);
1369 
1370 	/* not a proxy */
1371 	mono_mb_patch_branch (mb, pos);
1372 	mono_mb_emit_managed_call (mb, method, mono_method_signature (method));
1373 	mono_mb_emit_byte (mb, CEE_RET);
1374 #endif
1375 
1376 	info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
1377 	info->d.remoting.method = method;
1378 	res = mono_remoting_mb_create_and_cache (method, mb, sig, sig->param_count + 16, info);
1379 	mono_mb_free (mb);
1380 
1381 	return res;
1382 }
1383 
1384 /**
1385  * mono_marshal_get_ldfld_wrapper:
1386  * \param type the type of the field
1387  *
1388  * This method generates a function which can be use to load a field with type
1389  * \p type from an object. The generated function has the following signature:
1390  *
1391  * <code><i>type</i> ldfld_wrapper (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, int offset)</code>
1392  */
1393 MonoMethod *
mono_marshal_get_ldfld_wrapper(MonoType * type)1394 mono_marshal_get_ldfld_wrapper (MonoType *type)
1395 {
1396 	MonoMethodSignature *sig;
1397 	MonoMethodBuilder *mb;
1398 	MonoMethod *res;
1399 	MonoClass *klass;
1400 	GHashTable *cache;
1401 	WrapperInfo *info;
1402 	char *name;
1403 	int t, pos0, pos1 = 0;
1404 	static MonoMethod* tp_load = NULL;
1405 
1406 	type = mono_type_get_underlying_type (type);
1407 
1408 	t = type->type;
1409 
1410 	if (!type->byref) {
1411 		if (type->type == MONO_TYPE_SZARRAY) {
1412 			klass = mono_defaults.array_class;
1413 		} else if (type->type == MONO_TYPE_VALUETYPE) {
1414 			klass = type->data.klass;
1415 		} else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING) {
1416 			klass = mono_defaults.object_class;
1417 		} else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
1418 			klass = mono_defaults.int_class;
1419 		} else if (t == MONO_TYPE_GENERICINST) {
1420 			if (mono_type_generic_inst_is_valuetype (type))
1421 				klass = mono_class_from_mono_type (type);
1422 			else
1423 				klass = mono_defaults.object_class;
1424 		} else {
1425 			klass = mono_class_from_mono_type (type);
1426 		}
1427 	} else {
1428 		klass = mono_defaults.int_class;
1429 	}
1430 
1431 	cache = get_cache (&klass->image->ldfld_wrapper_cache, mono_aligned_addr_hash, NULL);
1432 	if ((res = mono_marshal_find_in_cache (cache, klass)))
1433 		return res;
1434 
1435 #ifndef DISABLE_REMOTING
1436 	if (!tp_load) {
1437 		tp_load = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "LoadRemoteFieldNew", -1);
1438 		g_assert (tp_load != NULL);
1439 	}
1440 #endif
1441 
1442 	/* we add the %p pointer value of klass because class names are not unique */
1443 	name = g_strdup_printf ("__ldfld_wrapper_%p_%s.%s", klass, klass->name_space, klass->name);
1444 	mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
1445 	g_free (name);
1446 
1447 	sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
1448 	sig->params [0] = &mono_defaults.object_class->byval_arg;
1449 	sig->params [1] = &mono_defaults.int_class->byval_arg;
1450 	sig->params [2] = &mono_defaults.int_class->byval_arg;
1451 	sig->params [3] = &mono_defaults.int_class->byval_arg;
1452 	sig->ret = &klass->byval_arg;
1453 
1454 #ifndef DISABLE_JIT
1455 	mono_mb_emit_ldarg (mb, 0);
1456 	pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1457 
1458 #ifndef DISABLE_REMOTING
1459 	mono_mb_emit_ldarg (mb, 0);
1460 	mono_mb_emit_ldarg (mb, 1);
1461 	mono_mb_emit_ldarg (mb, 2);
1462 
1463 	mono_mb_emit_managed_call (mb, tp_load, NULL);
1464 
1465 	/*
1466 	csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
1467 	csig->params [0] = &mono_defaults.object_class->byval_arg;
1468 	csig->params [1] = &mono_defaults.int_class->byval_arg;
1469 	csig->params [2] = &mono_defaults.int_class->byval_arg;
1470 	csig->ret = &klass->this_arg;
1471 	csig->pinvoke = 1;
1472 
1473 	mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
1474 	mono_marshal_emit_thread_interrupt_checkpoint (mb);
1475 	*/
1476 
1477 	if (klass->valuetype) {
1478 		mono_mb_emit_op (mb, CEE_UNBOX, klass);
1479 		pos1 = mono_mb_emit_branch (mb, CEE_BR);
1480 	} else {
1481 		mono_mb_emit_byte (mb, CEE_RET);
1482 	}
1483 #endif
1484 
1485 	mono_mb_patch_branch (mb, pos0);
1486 
1487 	mono_mb_emit_ldarg (mb, 0);
1488         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1489         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1490 	mono_mb_emit_ldarg (mb, 3);
1491 	mono_mb_emit_byte (mb, CEE_ADD);
1492 
1493 	if (klass->valuetype)
1494 		mono_mb_patch_branch (mb, pos1);
1495 
1496 	switch (t) {
1497 	case MONO_TYPE_I1:
1498 	case MONO_TYPE_U1:
1499 	case MONO_TYPE_BOOLEAN:
1500 	case MONO_TYPE_CHAR:
1501 	case MONO_TYPE_I2:
1502 	case MONO_TYPE_U2:
1503 	case MONO_TYPE_I4:
1504 	case MONO_TYPE_U4:
1505 	case MONO_TYPE_I8:
1506 	case MONO_TYPE_U8:
1507 	case MONO_TYPE_R4:
1508 	case MONO_TYPE_R8:
1509 	case MONO_TYPE_ARRAY:
1510 	case MONO_TYPE_SZARRAY:
1511 	case MONO_TYPE_OBJECT:
1512 	case MONO_TYPE_CLASS:
1513 	case MONO_TYPE_STRING:
1514 	case MONO_TYPE_I:
1515 	case MONO_TYPE_U:
1516 	case MONO_TYPE_PTR:
1517 	case MONO_TYPE_FNPTR:
1518 		mono_mb_emit_byte (mb, mono_type_to_ldind (type));
1519 		break;
1520 	case MONO_TYPE_VALUETYPE:
1521 		g_assert (!klass->enumtype);
1522 		mono_mb_emit_op (mb, CEE_LDOBJ, klass);
1523 		break;
1524 	case MONO_TYPE_GENERICINST:
1525 		if (mono_type_generic_inst_is_valuetype (type)) {
1526 			mono_mb_emit_op (mb, CEE_LDOBJ, klass);
1527 		} else {
1528 			mono_mb_emit_byte (mb, CEE_LDIND_REF);
1529 		}
1530 		break;
1531 	case MONO_TYPE_VAR:
1532 	case MONO_TYPE_MVAR:
1533 		mono_mb_emit_op (mb, CEE_LDOBJ, klass);
1534 		break;
1535 	default:
1536 		g_warning ("type %x not implemented", type->type);
1537 		g_assert_not_reached ();
1538 	}
1539 
1540 	mono_mb_emit_byte (mb, CEE_RET);
1541 #endif /* DISABLE_JIT */
1542 
1543 	info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
1544 	info->d.proxy.klass = klass;
1545 	res = mono_mb_create_and_cache_full (cache, klass,
1546 										 mb, sig, sig->param_count + 16, info, NULL);
1547 	mono_mb_free (mb);
1548 
1549 	return res;
1550 }
1551 
1552 /*
1553  * mono_marshal_get_ldflda_wrapper:
1554  * @type: the type of the field
1555  *
1556  * This method generates a function which can be used to load a field address
1557  * from an object. The generated function has the following signature:
1558  * gpointer ldflda_wrapper (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, int offset);
1559  */
1560 MonoMethod *
mono_marshal_get_ldflda_wrapper(MonoType * type)1561 mono_marshal_get_ldflda_wrapper (MonoType *type)
1562 {
1563 	MonoMethodSignature *sig;
1564 	MonoMethodBuilder *mb;
1565 	MonoMethod *res;
1566 	MonoClass *klass;
1567 	GHashTable *cache;
1568 	WrapperInfo *info;
1569 	char *name;
1570 	int t, pos0, pos1, pos2, pos3;
1571 
1572 	type = mono_type_get_underlying_type (type);
1573 	t = type->type;
1574 
1575 	if (!type->byref) {
1576 		if (type->type == MONO_TYPE_SZARRAY) {
1577 			klass = mono_defaults.array_class;
1578 		} else if (type->type == MONO_TYPE_VALUETYPE) {
1579 			klass = type->data.klass;
1580 		} else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING) {
1581 			klass = mono_defaults.object_class;
1582 		} else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
1583 			klass = mono_defaults.int_class;
1584 		} else if (t == MONO_TYPE_GENERICINST) {
1585 			if (mono_type_generic_inst_is_valuetype (type))
1586 				klass = mono_class_from_mono_type (type);
1587 			else
1588 				klass = mono_defaults.object_class;
1589 		} else {
1590 			klass = mono_class_from_mono_type (type);
1591 		}
1592 	} else {
1593 		klass = mono_defaults.int_class;
1594 	}
1595 
1596 	cache = get_cache (&klass->image->ldflda_wrapper_cache, mono_aligned_addr_hash, NULL);
1597 	if ((res = mono_marshal_find_in_cache (cache, klass)))
1598 		return res;
1599 
1600 	/* we add the %p pointer value of klass because class names are not unique */
1601 	name = g_strdup_printf ("__ldflda_wrapper_%p_%s.%s", klass, klass->name_space, klass->name);
1602 	mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLDA);
1603 	g_free (name);
1604 
1605 	sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
1606 	sig->params [0] = &mono_defaults.object_class->byval_arg;
1607 	sig->params [1] = &mono_defaults.int_class->byval_arg;
1608 	sig->params [2] = &mono_defaults.int_class->byval_arg;
1609 	sig->params [3] = &mono_defaults.int_class->byval_arg;
1610 	sig->ret = &mono_defaults.int_class->byval_arg;
1611 
1612 #ifndef DISABLE_JIT
1613 	/* if typeof (this) != transparent_proxy goto pos0 */
1614 	mono_mb_emit_ldarg (mb, 0);
1615 	pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1616 
1617 	/* if same_appdomain goto pos1 */
1618 	mono_mb_emit_ldarg (mb, 0);
1619 	pos1 = mono_mb_emit_xdomain_check (mb, CEE_BEQ);
1620 
1621 	mono_mb_emit_exception_full (mb, "System", "InvalidOperationException", "Attempt to load field address from object in another appdomain.");
1622 
1623 	/* same app domain */
1624 	mono_mb_patch_branch (mb, pos1);
1625 
1626 	/* if typeof (this) != contextbound goto pos2 */
1627 	mono_mb_emit_ldarg (mb, 0);
1628 	pos2 = mono_mb_emit_contextbound_check (mb, CEE_BEQ);
1629 
1630 	/* if this->rp->context == mono_context_get goto pos3 */
1631 	mono_mb_emit_ldarg (mb, 0);
1632 	mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp));
1633 	mono_mb_emit_byte (mb, CEE_LDIND_REF);
1634 	mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoRealProxy, context));
1635 	mono_mb_emit_byte (mb, CEE_LDIND_REF);
1636 	mono_mb_emit_icall (mb, mono_context_get_icall);
1637 	pos3 = mono_mb_emit_branch (mb, CEE_BEQ);
1638 
1639 	mono_mb_emit_exception_full (mb, "System", "InvalidOperationException", "Attempt to load field address from object in another context.");
1640 
1641 	mono_mb_patch_branch (mb, pos2);
1642 	mono_mb_patch_branch (mb, pos3);
1643 
1644 	/* return the address of the field from this->rp->unwrapped_server */
1645 	mono_mb_emit_ldarg (mb, 0);
1646 	mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp));
1647 	mono_mb_emit_byte (mb, CEE_LDIND_REF);
1648 	mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoRealProxy, unwrapped_server));
1649 	mono_mb_emit_byte (mb, CEE_LDIND_REF);
1650 	mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1651 	mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1652 	mono_mb_emit_ldarg (mb, 3);
1653 	mono_mb_emit_byte (mb, CEE_ADD);
1654 	mono_mb_emit_byte (mb, CEE_RET);
1655 
1656 	/* not a proxy: return the address of the field directly */
1657 	mono_mb_patch_branch (mb, pos0);
1658 
1659 	mono_mb_emit_ldarg (mb, 0);
1660         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1661         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1662 	mono_mb_emit_ldarg (mb, 3);
1663 	mono_mb_emit_byte (mb, CEE_ADD);
1664 
1665 	mono_mb_emit_byte (mb, CEE_RET);
1666 #endif
1667 
1668 	info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
1669 	info->d.proxy.klass = klass;
1670 	res = mono_mb_create_and_cache_full (cache, klass,
1671 										 mb, sig, sig->param_count + 16,
1672 										 info, NULL);
1673 	mono_mb_free (mb);
1674 
1675 	return res;
1676 }
1677 
1678 
1679 /**
1680  * mono_marshal_get_stfld_wrapper:
1681  * \param type the type of the field
1682  *
1683  * This method generates a function which can be use to store a field with type
1684  * \p type. The generated function has the following signature:
1685  *
1686  * <code>void stfld_wrapper (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, int offset, <i>type</i> val)</code>
1687  */
1688 MonoMethod *
mono_marshal_get_stfld_wrapper(MonoType * type)1689 mono_marshal_get_stfld_wrapper (MonoType *type)
1690 {
1691 	MonoMethodSignature *sig;
1692 	MonoMethodBuilder *mb;
1693 	MonoMethod *res;
1694 	MonoClass *klass;
1695 	GHashTable *cache;
1696 	WrapperInfo *info;
1697 	char *name;
1698 	int t, pos;
1699 	static MonoMethod *tp_store = NULL;
1700 
1701 	type = mono_type_get_underlying_type (type);
1702 	t = type->type;
1703 
1704 	if (!type->byref) {
1705 		if (type->type == MONO_TYPE_SZARRAY) {
1706 			klass = mono_defaults.array_class;
1707 		} else if (type->type == MONO_TYPE_VALUETYPE) {
1708 			klass = type->data.klass;
1709 		} else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING) {
1710 			klass = mono_defaults.object_class;
1711 		} else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
1712 			klass = mono_defaults.int_class;
1713 		} else if (t == MONO_TYPE_GENERICINST) {
1714 			if (mono_type_generic_inst_is_valuetype (type))
1715 				klass = mono_class_from_mono_type (type);
1716 			else
1717 				klass = mono_defaults.object_class;
1718 		} else {
1719 			klass = mono_class_from_mono_type (type);
1720 		}
1721 	} else {
1722 		klass = mono_defaults.int_class;
1723 	}
1724 
1725 	cache = get_cache (&klass->image->stfld_wrapper_cache, mono_aligned_addr_hash, NULL);
1726 	if ((res = mono_marshal_find_in_cache (cache, klass)))
1727 		return res;
1728 
1729 #ifndef DISABLE_REMOTING
1730 	if (!tp_store) {
1731 		tp_store = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "StoreRemoteField", -1);
1732 		g_assert (tp_store != NULL);
1733 	}
1734 #endif
1735 
1736 	/* we add the %p pointer value of klass because class names are not unique */
1737 	name = g_strdup_printf ("__stfld_wrapper_%p_%s.%s", klass, klass->name_space, klass->name);
1738 	mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
1739 	g_free (name);
1740 
1741 	sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
1742 	sig->params [0] = &mono_defaults.object_class->byval_arg;
1743 	sig->params [1] = &mono_defaults.int_class->byval_arg;
1744 	sig->params [2] = &mono_defaults.int_class->byval_arg;
1745 	sig->params [3] = &mono_defaults.int_class->byval_arg;
1746 	sig->params [4] = &klass->byval_arg;
1747 	sig->ret = &mono_defaults.void_class->byval_arg;
1748 
1749 #ifndef DISABLE_JIT
1750 	mono_mb_emit_ldarg (mb, 0);
1751 	pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1752 
1753 #ifndef DISABLE_REMOTING
1754 	mono_mb_emit_ldarg (mb, 0);
1755 	mono_mb_emit_ldarg (mb, 1);
1756 	mono_mb_emit_ldarg (mb, 2);
1757 	mono_mb_emit_ldarg (mb, 4);
1758 	if (klass->valuetype)
1759 		mono_mb_emit_op (mb, CEE_BOX, klass);
1760 
1761 	mono_mb_emit_managed_call (mb, tp_store, NULL);
1762 
1763 	mono_mb_emit_byte (mb, CEE_RET);
1764 #endif
1765 
1766 	mono_mb_patch_branch (mb, pos);
1767 
1768 	mono_mb_emit_ldarg (mb, 0);
1769         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1770         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1771 	mono_mb_emit_ldarg (mb, 3);
1772 	mono_mb_emit_byte (mb, CEE_ADD);
1773 	mono_mb_emit_ldarg (mb, 4);
1774 
1775 	switch (t) {
1776 	case MONO_TYPE_I1:
1777 	case MONO_TYPE_U1:
1778 	case MONO_TYPE_BOOLEAN:
1779 	case MONO_TYPE_CHAR:
1780 	case MONO_TYPE_I2:
1781 	case MONO_TYPE_U2:
1782 	case MONO_TYPE_I4:
1783 	case MONO_TYPE_U4:
1784 	case MONO_TYPE_I8:
1785 	case MONO_TYPE_U8:
1786 	case MONO_TYPE_R4:
1787 	case MONO_TYPE_R8:
1788 	case MONO_TYPE_ARRAY:
1789 	case MONO_TYPE_SZARRAY:
1790 	case MONO_TYPE_OBJECT:
1791 	case MONO_TYPE_CLASS:
1792 	case MONO_TYPE_STRING:
1793 	case MONO_TYPE_I:
1794 	case MONO_TYPE_U:
1795 	case MONO_TYPE_PTR:
1796 	case MONO_TYPE_FNPTR:
1797 		mono_mb_emit_byte (mb, mono_type_to_stind (type));
1798 		break;
1799 	case MONO_TYPE_VALUETYPE:
1800 		g_assert (!klass->enumtype);
1801 		mono_mb_emit_op (mb, CEE_STOBJ, klass);
1802 		break;
1803 	case MONO_TYPE_GENERICINST:
1804 	case MONO_TYPE_VAR:
1805 	case MONO_TYPE_MVAR:
1806 		mono_mb_emit_op (mb, CEE_STOBJ, klass);
1807 		break;
1808 	default:
1809 		g_warning ("type %x not implemented", type->type);
1810 		g_assert_not_reached ();
1811 	}
1812 
1813 	mono_mb_emit_byte (mb, CEE_RET);
1814 #endif
1815 
1816 	info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
1817 	info->d.proxy.klass = klass;
1818 	res = mono_mb_create_and_cache_full (cache, klass,
1819 										 mb, sig, sig->param_count + 16,
1820 										 info, NULL);
1821 	mono_mb_free (mb);
1822 
1823 	return res;
1824 }
1825 
1826 /**
1827  * mono_marshal_get_proxy_cancast:
1828  */
1829 MonoMethod *
mono_marshal_get_proxy_cancast(MonoClass * klass)1830 mono_marshal_get_proxy_cancast (MonoClass *klass)
1831 {
1832 	static MonoMethodSignature *isint_sig = NULL;
1833 	GHashTable *cache;
1834 	MonoMethod *res;
1835 	WrapperInfo *info;
1836 	int pos_failed, pos_end;
1837 	char *name, *klass_name;
1838 	MonoMethod *can_cast_to;
1839 	MonoMethodDesc *desc;
1840 	MonoMethodBuilder *mb;
1841 
1842 	cache = get_cache (&klass->image->proxy_isinst_cache, mono_aligned_addr_hash, NULL);
1843 	if ((res = mono_marshal_find_in_cache (cache, klass)))
1844 		return res;
1845 
1846 	if (!isint_sig) {
1847 		isint_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
1848 		isint_sig->params [0] = &mono_defaults.object_class->byval_arg;
1849 		isint_sig->ret = &mono_defaults.object_class->byval_arg;
1850 		isint_sig->pinvoke = 0;
1851 	}
1852 
1853 	klass_name = mono_type_full_name (&klass->byval_arg);
1854 	name = g_strdup_printf ("__proxy_isinst_wrapper_%s", klass_name);
1855 	mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_PROXY_ISINST);
1856 	g_free (klass_name);
1857 	g_free (name);
1858 
1859 	mb->method->save_lmf = 1;
1860 
1861 #ifndef DISABLE_JIT
1862 	/* get the real proxy from the transparent proxy*/
1863 	mono_mb_emit_ldarg (mb, 0);
1864 	mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp));
1865 	mono_mb_emit_byte (mb, CEE_LDIND_REF);
1866 
1867 	/* get the reflection type from the type handle */
1868 	mono_mb_emit_ptr (mb, &klass->byval_arg);
1869 	mono_mb_emit_icall (mb, type_from_handle);
1870 
1871 	mono_mb_emit_ldarg (mb, 0);
1872 
1873 	/* make the call to CanCastTo (type, ob) */
1874 	desc = mono_method_desc_new ("IRemotingTypeInfo:CanCastTo", FALSE);
1875 	can_cast_to = mono_method_desc_search_in_class (desc, mono_defaults.iremotingtypeinfo_class);
1876 	g_assert (can_cast_to);
1877 	mono_method_desc_free (desc);
1878 	mono_mb_emit_op (mb, CEE_CALLVIRT, can_cast_to);
1879 
1880 	pos_failed = mono_mb_emit_branch (mb, CEE_BRFALSE);
1881 
1882 	/* Upgrade the proxy vtable by calling: mono_upgrade_remote_class_wrapper (type, ob)*/
1883 	mono_mb_emit_ptr (mb, &klass->byval_arg);
1884 	mono_mb_emit_icall (mb, type_from_handle);
1885 	mono_mb_emit_ldarg (mb, 0);
1886 
1887 	mono_mb_emit_icall (mb, mono_upgrade_remote_class_wrapper);
1888 	mono_marshal_emit_thread_interrupt_checkpoint (mb);
1889 
1890 	mono_mb_emit_ldarg (mb, 0);
1891 	pos_end = mono_mb_emit_branch (mb, CEE_BR);
1892 
1893 	/* fail */
1894 
1895 	mono_mb_patch_branch (mb, pos_failed);
1896 	mono_mb_emit_byte (mb, CEE_LDNULL);
1897 
1898 	/* the end */
1899 
1900 	mono_mb_patch_branch (mb, pos_end);
1901 	mono_mb_emit_byte (mb, CEE_RET);
1902 #endif
1903 
1904 	info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
1905 	info->d.proxy.klass = klass;
1906 	res = mono_mb_create_and_cache_full (cache, klass, mb, isint_sig, isint_sig->param_count + 16, info, NULL);
1907 	mono_mb_free (mb);
1908 
1909 	return res;
1910 }
1911 
1912 void
mono_upgrade_remote_class_wrapper(MonoReflectionType * rtype_raw,MonoTransparentProxy * tproxy_raw)1913 mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype_raw, MonoTransparentProxy *tproxy_raw)
1914 {
1915 	ICALL_ENTRY ();
1916 	MONO_HANDLE_DCL (MonoReflectionType, rtype);
1917 	MONO_HANDLE_DCL (MonoTransparentProxy, tproxy);
1918 	MonoDomain *domain = MONO_HANDLE_DOMAIN (tproxy);
1919 	MonoClass *klass = mono_class_from_mono_type (MONO_HANDLE_GETVAL (rtype, type));
1920 	mono_upgrade_remote_class (domain, MONO_HANDLE_CAST (MonoObject, tproxy), klass, &error);
1921 	ICALL_RETURN ();
1922 }
1923 
1924 #else /* DISABLE_REMOTING */
1925 
1926 void
mono_remoting_init(void)1927 mono_remoting_init (void)
1928 {
1929 }
1930 
1931 #endif /* DISABLE_REMOTING */
1932 
1933 /* mono_get_xdomain_marshal_type()
1934  * Returns the kind of marshalling that a type needs for cross domain calls.
1935  */
1936 static MonoXDomainMarshalType
mono_get_xdomain_marshal_type(MonoType * t)1937 mono_get_xdomain_marshal_type (MonoType *t)
1938 {
1939 	switch (t->type) {
1940 	case MONO_TYPE_VOID:
1941 		g_assert_not_reached ();
1942 		break;
1943 	case MONO_TYPE_U1:
1944 	case MONO_TYPE_I1:
1945 	case MONO_TYPE_BOOLEAN:
1946 	case MONO_TYPE_U2:
1947 	case MONO_TYPE_I2:
1948 	case MONO_TYPE_CHAR:
1949 	case MONO_TYPE_U4:
1950 	case MONO_TYPE_I4:
1951 	case MONO_TYPE_I8:
1952 	case MONO_TYPE_U8:
1953 	case MONO_TYPE_R4:
1954 	case MONO_TYPE_R8:
1955 		return MONO_MARSHAL_NONE;
1956 	case MONO_TYPE_STRING:
1957 		return MONO_MARSHAL_COPY;
1958 	case MONO_TYPE_ARRAY:
1959 	case MONO_TYPE_SZARRAY: {
1960 		MonoClass *elem_class = mono_class_from_mono_type (t)->element_class;
1961 		if (mono_get_xdomain_marshal_type (&(elem_class->byval_arg)) != MONO_MARSHAL_SERIALIZE)
1962 			return MONO_MARSHAL_COPY;
1963 		break;
1964 	}
1965 	default:
1966 		break;
1967 	}
1968 	return MONO_MARSHAL_SERIALIZE;
1969 }
1970 
1971 /* Replace the given array element by a copy in the current domain */
1972 static gboolean
xdomain_copy_array_element_inplace(MonoArrayHandle arr,int i,MonoError * error)1973 xdomain_copy_array_element_inplace (MonoArrayHandle arr, int i, MonoError *error)
1974 {
1975 	HANDLE_FUNCTION_ENTER ();
1976 	error_init (error);
1977 	MonoObjectHandle item = MONO_HANDLE_NEW (MonoObject, NULL);
1978 	MONO_HANDLE_ARRAY_GETREF (item, arr, i);
1979 
1980 	MonoObjectHandle item_copy = mono_marshal_xdomain_copy_value_handle (item, error);
1981 	goto_if_nok (error, leave);
1982 	MONO_HANDLE_ARRAY_SETREF (arr, i, item_copy);
1983 leave:
1984 	HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
1985 }
1986 
1987 /**
1988  * mono_marshal_xdomain_copy_value_handle:
1989  * \param val The value to copy.
1990  * \param error set on failure.
1991  * Makes a copy of \p val suitable for the current domain.
1992  * On failure returns NULL and sets \p error.
1993  */
1994 MonoObjectHandle
mono_marshal_xdomain_copy_value_handle(MonoObjectHandle val,MonoError * error)1995 mono_marshal_xdomain_copy_value_handle (MonoObjectHandle val, MonoError *error)
1996 {
1997 	error_init (error);
1998 	MonoObjectHandle result = MONO_HANDLE_NEW (MonoObject, NULL);
1999 	if (MONO_HANDLE_IS_NULL (val))
2000 		goto leave;
2001 
2002 	MonoDomain *domain = mono_domain_get ();
2003 
2004 	MonoClass *klass = mono_handle_class (val);
2005 
2006 	switch (klass->byval_arg.type) {
2007 	case MONO_TYPE_VOID:
2008 		g_assert_not_reached ();
2009 		break;
2010 	case MONO_TYPE_U1:
2011 	case MONO_TYPE_I1:
2012 	case MONO_TYPE_BOOLEAN:
2013 	case MONO_TYPE_U2:
2014 	case MONO_TYPE_I2:
2015 	case MONO_TYPE_CHAR:
2016 	case MONO_TYPE_U4:
2017 	case MONO_TYPE_I4:
2018 	case MONO_TYPE_I8:
2019 	case MONO_TYPE_U8:
2020 	case MONO_TYPE_R4:
2021 	case MONO_TYPE_R8: {
2022 		uint32_t gchandle = mono_gchandle_from_handle (val, TRUE);
2023 		MonoObjectHandle res = MONO_HANDLE_NEW (MonoObject, mono_value_box_checked (domain, klass, ((char*)val) + sizeof(MonoObject), error)); /* FIXME use handles in mono_value_box_checked */
2024 		mono_gchandle_free (gchandle);
2025 		goto_if_nok (error, leave);
2026 		MONO_HANDLE_ASSIGN (result, res);
2027 		break;
2028 	}
2029 	case MONO_TYPE_STRING: {
2030 		MonoStringHandle str = MONO_HANDLE_CAST (MonoString, val);
2031 		uint32_t gchandle = mono_gchandle_from_handle (val, TRUE);
2032 		MonoStringHandle res = mono_string_new_utf16_handle (domain, mono_string_chars (MONO_HANDLE_RAW (str)), mono_string_handle_length (str), error);
2033 		mono_gchandle_free (gchandle);
2034 		goto_if_nok (error, leave);
2035 		MONO_HANDLE_ASSIGN (result, res);
2036 		break;
2037 	}
2038 	case MONO_TYPE_ARRAY:
2039 	case MONO_TYPE_SZARRAY: {
2040 		MonoArrayHandle arr = MONO_HANDLE_CAST (MonoArray, val);
2041 		MonoXDomainMarshalType mt = mono_get_xdomain_marshal_type (&klass->element_class->byval_arg);
2042 		if (mt == MONO_MARSHAL_SERIALIZE)
2043 			goto leave;
2044 		MonoArrayHandle acopy = mono_array_clone_in_domain (domain, arr, error);
2045 		goto_if_nok (error, leave);
2046 
2047 		if (mt == MONO_MARSHAL_COPY) {
2048 			int i, len = mono_array_handle_length (acopy);
2049 			for (i = 0; i < len; i++) {
2050 				if (!xdomain_copy_array_element_inplace (acopy, i, error))
2051 					goto leave;
2052 			}
2053 		}
2054 		MONO_HANDLE_ASSIGN (result, acopy);
2055 		break;
2056 	}
2057 	default:
2058 		break;
2059 	}
2060 
2061 leave:
2062 	return result;
2063 }
2064 
2065 /* mono_marshal_xdomain_copy_value
2066  * Makes a copy of "val" suitable for the current domain.
2067  */
2068 MonoObject*
mono_marshal_xdomain_copy_value(MonoObject * val_raw,MonoError * error)2069 mono_marshal_xdomain_copy_value (MonoObject* val_raw, MonoError *error)
2070 {
2071 	HANDLE_FUNCTION_ENTER ();
2072 	/* FIXME callers of mono_marshal_xdomain_copy_value should use handles */
2073 	MONO_HANDLE_DCL (MonoObject, val);
2074 	MonoObjectHandle result = mono_marshal_xdomain_copy_value_handle (val, error);
2075 	HANDLE_FUNCTION_RETURN_OBJ (result);
2076 }
2077 
2078 /* mono_marshal_xdomain_copy_value
2079  * Makes a copy of "val" suitable for the current domain.
2080  */
2081 MonoObject *
ves_icall_mono_marshal_xdomain_copy_value(MonoObject * val)2082 ves_icall_mono_marshal_xdomain_copy_value (MonoObject *val)
2083 {
2084 	MonoError error;
2085 	MonoObject *result = mono_marshal_xdomain_copy_value (val, &error);
2086 	mono_error_set_pending_exception (&error);
2087 	return result;
2088 }
2089 
2090 void
mono_context_set_icall(MonoAppContext * new_context_raw)2091 mono_context_set_icall (MonoAppContext *new_context_raw)
2092 {
2093 	HANDLE_FUNCTION_ENTER ();
2094 	MONO_HANDLE_DCL (MonoAppContext, new_context);
2095 	mono_context_set_handle (new_context);
2096 	HANDLE_FUNCTION_RETURN ();
2097 }
2098 
2099 static MonoAppContext*
mono_context_get_icall(void)2100 mono_context_get_icall (void)
2101 {
2102 	HANDLE_FUNCTION_ENTER ();
2103 	MonoAppContextHandle context = mono_context_get_handle ();
2104 	HANDLE_FUNCTION_RETURN_OBJ (context);
2105 }
2106