Exemple #1
0
String GDMonoMethod::get_ret_type_full_name() const {
	MonoMethodSignature *method_sig = mono_method_signature(mono_method);
	char *ret_str = mono_type_full_name(mono_signature_get_return_type(method_sig));
	String res = ret_str;
	mono_free(ret_str);
	return res;
}
int printObjectSize(MonoObject* obj, MonoType* type, int total) 
{
  total += mono_object_get_size (obj);
  LL_INFOS() << "Object type: " << mono_type_full_name(type) << " size: "
	  << total << LL_ENDL;
    
  return total;
}
Exemple #3
0
int printObjectSize(MonoObject* obj, MonoType* type, int total) 
{
  total += mono_object_get_size (obj);
  llinfos << "Object type: " << mono_type_full_name(type) << " size: "
	  << total << llendl;
    
  return total;
}
Exemple #4
0
static int
dump_verify_info (MonoImage *image, int flags)
{
	GSList *errors, *tmp;
	int count = 0, verifiable = 0;
	const char* desc [] = {
		"Ok", "Error", "Warning", NULL, "CLS", NULL, NULL, NULL, "Not Verifiable"
	};

	if (verify_code) { /* verify code */
		int i;
		MonoTableInfo *m = &image->tables [MONO_TABLE_METHOD];

		for (i = 0; i < m->rows; ++i) {
			MonoMethod *method;
			MonoError error;

			method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i+1), NULL, NULL, &error);
			if (!method) {
				g_print ("Warning: Cannot lookup method with token 0x%08x due to %s\n", i + 1, mono_error_get_message (&error));
				mono_error_cleanup (&error);
				continue;
			}
			errors = mono_method_verify (method, flags);
			if (errors) {
				MonoClass *klass = mono_method_get_class (method);
				char *name = mono_type_full_name (&klass->byval_arg);
				if (mono_method_signature (method) == NULL) {
					g_print ("In method: %s::%s(ERROR)\n", name, mono_method_get_name (method));
				} else {
					char *sig;
					sig = mono_signature_get_desc (mono_method_signature (method), FALSE);	
					g_print ("In method: %s::%s(%s)\n", name, mono_method_get_name (method), sig);
					g_free (sig);
				}
				g_free (name);
			}

			for (tmp = errors; tmp; tmp = tmp->next) {
				MonoVerifyInfo *info = (MonoVerifyInfo *)tmp->data;
				g_print ("%s: %s\n", desc [info->status], info->message);
				if (info->status == MONO_VERIFY_ERROR) {
					count++;
					verifiable = 3;
				}
				if(info->status == MONO_VERIFY_NOT_VERIFIABLE) {
					if (verifiable < 2)
						verifiable = 2;	
				}
			}
			mono_free_verify_list (errors);
		}
	}

	if (count)
		g_print ("Error count: %d\n", count);
	return verifiable;
}
Exemple #5
0
String get_exception_name_and_message(MonoException *p_exc) {
	String res;

	MonoClass *klass = mono_object_get_class((MonoObject *)p_exc);
	MonoType *type = mono_class_get_type(klass);

	char *full_name = mono_type_full_name(type);
	res += full_name;
	mono_free(full_name);

	res += ": ";

	MonoProperty *prop = mono_class_get_property_from_name(klass, "Message");
	MonoString *msg = (MonoString *)property_get_value(prop, (MonoObject *)p_exc, NULL, NULL);
	res += GDMonoMarshal::mono_string_to_godot(msg);

	return res;
}
Exemple #6
0
static MonoString*
get_type_name_as_mono_string (MonoErrorInternal *error, MonoDomain *domain, MonoError *error_out)
{
	MonoString* res = NULL;

	if (error->type_name) {
		res = mono_string_new (domain, error->type_name);
		
	} else if (error->klass) {
		char *name = mono_type_full_name (&error->klass->byval_arg);
		if (name) {
			res = mono_string_new (domain, name);
			g_free (name);
		}
	}
	if (!res)
		mono_error_set_out_of_memory (error_out, "Could not allocate type name");
	return res;
}
Exemple #7
0
String GDMonoMethod::get_full_name_no_class() const {
	String res;

	MonoMethodSignature *method_sig = mono_method_signature(mono_method);

	char *ret_str = mono_type_full_name(mono_signature_get_return_type(method_sig));
	res += ret_str;
	mono_free(ret_str);

	res += " ";
	res += name;
	res += "(";

	char *sig_desc = mono_signature_get_desc(method_sig, true);
	res += sig_desc;
	mono_free(sig_desc);

	res += ")";

	return res;
}
Exemple #8
0
static MonoStringHandle
get_type_name_as_mono_string (MonoErrorInternal *error, MonoDomain *domain, MonoError *error_out)
{
	HANDLE_FUNCTION_ENTER ();

	MonoStringHandle res = NULL_HANDLE_STRING;

	if (error->type_name) {
		res = string_new_cleanup (domain, error->type_name);
	} else {
		MonoClass *klass = get_class (error);
		if (klass) {
			char *name = mono_type_full_name (m_class_get_byval_arg (klass));
			if (name) {
				res = string_new_cleanup (domain, name);
				g_free (name);
			}
		}
	}
	if (MONO_HANDLE_IS_NULL (res))
		mono_error_set_out_of_memory (error_out, "Could not allocate type name");
	HANDLE_FUNCTION_RETURN_REF (MonoString, res);
}
Exemple #9
0
gboolean
mono_class_is_magic_float (MonoClass *klass)
{
	static MonoClass *magic_nfloat_class;

	if (klass == magic_nfloat_class)
		return TRUE;

	if (magic_nfloat_class)
		return FALSE;

	if (!mono_class_is_magic_assembly (klass))
		return FALSE;

	if (strcmp ("System", m_class_get_name_space (klass)) != 0)
		return FALSE;

	if (strcmp ("nfloat", m_class_get_name (klass)) == 0) {
		magic_nfloat_class = klass;

		/* Assert that we are using the matching assembly */
		MonoClassField *value_field = mono_class_get_field_from_name_full (klass, "v", NULL);
		g_assert (value_field);
		MonoType *t = mono_field_get_type (value_field);
		MonoType *native = mini_native_type_replace_type (m_class_get_byval_arg (klass));
		if (t->type != native->type)
			g_error ("Assembly used for native types '%s' doesn't match this runtime, %s is mapped to %s, expecting %s.\n", m_class_get_image (klass)->name, m_class_get_name (klass), mono_type_full_name (t), mono_type_full_name (native));
		return TRUE;
	}
	return FALSE;
}
Exemple #10
0
gpointer
mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
{
	GSharedVtCallInfo *info;
	CallInfo *caller_cinfo, *callee_cinfo;
	MonoMethodSignature *caller_sig, *callee_sig;
	int aindex, i;
	gboolean var_ret = FALSE;
	CallInfo *cinfo, *gcinfo;
	MonoMethodSignature *sig, *gsig;
	GPtrArray *map;

	if (gsharedvt_in) {
		caller_sig = normal_sig;
		callee_sig = gsharedvt_sig;
		caller_cinfo = mono_arch_get_call_info (NULL, caller_sig);
		callee_cinfo = mono_arch_get_call_info (NULL, callee_sig);
	} else {
		callee_sig = normal_sig;
		caller_sig = gsharedvt_sig;
		callee_cinfo = mono_arch_get_call_info (NULL, callee_sig);
		caller_cinfo = mono_arch_get_call_info (NULL, caller_sig);
	}

	/*
	 * If GSHAREDVT_IN is true, this means we are transitioning from normal to gsharedvt code. The caller uses the
	 * normal call signature, while the callee uses the gsharedvt signature.
	 * If GSHAREDVT_IN is false, its the other way around.
	 */

	/* sig/cinfo describes the normal call, while gsig/gcinfo describes the gsharedvt call */
	if (gsharedvt_in) {
		sig = caller_sig;
		gsig = callee_sig;
		cinfo = caller_cinfo;
		gcinfo = callee_cinfo;
	} else {
		sig = callee_sig;
		gsig = caller_sig;
		cinfo = callee_cinfo;
		gcinfo = caller_cinfo;
	}

	DEBUG_AMD64_GSHAREDVT_PRINT ("source sig: (%s) return (%s)\n", mono_signature_get_desc (caller_sig, FALSE), mono_type_full_name (mono_signature_get_return_type (caller_sig))); // Leak
	DEBUG_AMD64_GSHAREDVT_PRINT ("dest sig: (%s) return (%s)\n", mono_signature_get_desc (callee_sig, FALSE), mono_type_full_name (mono_signature_get_return_type (callee_sig)));

	if (gcinfo->ret.storage == ArgGsharedvtVariableInReg) {
		/*
		 * The return type is gsharedvt
		 */
		var_ret = TRUE;
	}

	/*
	 * The stack looks like this:
	 * <arguments>
	 * <trampoline frame>
	 * <call area>
	 * We have to map the stack slots in <arguments> to the stack slots in <call area>.
	 */
	map = g_ptr_array_new ();

	for (aindex = 0; aindex < cinfo->nargs; ++aindex) {
		ArgInfo *src_info = &caller_cinfo->args [aindex];
		ArgInfo *dst_info = &callee_cinfo->args [aindex];
		int *src = NULL, *dst = NULL;
		int nsrc = -1, ndst = -1, nslots = 0;

		int arg_marshal = GSHAREDVT_ARG_NONE;
		int arg_slots = 0; // Size in quadwords
		DEBUG_AMD64_GSHAREDVT_PRINT ("-- arg %d in (%s) out (%s)\n", aindex, arg_info_desc (src_info), arg_info_desc (dst_info));

		switch (src_info->storage) {
		case ArgInIReg:
		case ArgInDoubleSSEReg:
		case ArgInFloatSSEReg:
		case ArgValuetypeInReg:
		case ArgOnStack:
			nsrc = get_arg_slots (src_info, &src, TRUE);
			break;
		case ArgGSharedVtInReg:
			handle_marshal_when_src_gsharedvt (dst_info, &arg_marshal, &arg_slots);
			handle_map_when_gsharedvt_in_reg (src_info, &nsrc, &src);
			break;
		case ArgGSharedVtOnStack:
			handle_marshal_when_src_gsharedvt (dst_info, &arg_marshal, &arg_slots);
			handle_map_when_gsharedvt_on_stack (src_info, &nsrc, &src, TRUE);
			break;
		case ArgValuetypeAddrInIReg:
		case ArgValuetypeAddrOnStack:
			nsrc = get_arg_slots (src_info, &src, TRUE);
			break;
		default:
			g_error ("Gsharedvt can't handle source arg type %d", (int)src_info->storage); // Inappropriate value: ArgValuetypeAddrInIReg is for returns only
		}

		switch (dst_info->storage) {
		case ArgInIReg:
		case ArgInDoubleSSEReg:
		case ArgInFloatSSEReg:
		case ArgOnStack:
		case ArgValuetypeInReg:
			ndst = get_arg_slots (dst_info, &dst, FALSE);
			break;
		case ArgGSharedVtInReg:
			handle_marshal_when_dst_gsharedvt (src_info, &arg_marshal);
			handle_map_when_gsharedvt_in_reg (dst_info, &ndst, &dst);
			break;
		case ArgGSharedVtOnStack:
			handle_marshal_when_dst_gsharedvt (src_info, &arg_marshal);
			handle_map_when_gsharedvt_on_stack (dst_info, &ndst, &dst, FALSE);
			break;
		case ArgValuetypeAddrInIReg:
		case ArgValuetypeAddrOnStack:
			ndst = get_arg_slots (dst_info, &dst, FALSE);
			break;
		default:
			g_error ("Gsharedvt can't handle dest arg type %d", (int)dst_info->storage); // See above
		}
		if (nsrc)
			src [0] |= (arg_marshal << SRC_DESCRIPTOR_MARSHAL_SHIFT) | (arg_slots << SLOT_COUNT_SHIFT);

		/* Merge and add to the global list*/
		nslots = MIN (nsrc, ndst);
		DEBUG_AMD64_GSHAREDVT_PRINT ("nsrc %d ndst %d\n", nsrc, ndst);

		for (i = 0; i < nslots; ++i)
			add_to_map (map, src [i], dst [i]);

		g_free (src);
		g_free (dst);
	}

	DEBUG_AMD64_GSHAREDVT_PRINT ("-- return in (%s) out (%s) var_ret %d\n", arg_info_desc (&caller_cinfo->ret),  arg_info_desc (&callee_cinfo->ret), var_ret);

	if (cinfo->ret.storage == ArgValuetypeAddrInIReg) {
		/* Both the caller and the callee pass the vtype ret address in r8 (System V) and RCX or RDX (Windows) */
		g_assert (gcinfo->ret.storage == ArgValuetypeAddrInIReg || gcinfo->ret.storage == ArgGsharedvtVariableInReg);
		add_to_map (map, map_reg (cinfo->ret.reg), map_reg (cinfo->ret.reg));
	}

	info = mono_domain_alloc0 (mono_domain_get (), sizeof (GSharedVtCallInfo) + (map->len * sizeof (int)));
	info->addr = addr;
	info->stack_usage = callee_cinfo->stack_usage;
	info->ret_marshal = GSHAREDVT_RET_NONE;
	info->gsharedvt_in = gsharedvt_in ? 1 : 0;
	info->vret_slot = -1;
	info->calli = calli;

	if (var_ret) {
		g_assert (gcinfo->ret.storage == ArgGsharedvtVariableInReg);
		info->vret_arg_reg = map_reg (gcinfo->ret.reg);
		DEBUG_AMD64_GSHAREDVT_PRINT ("mapping vreg_arg_reg to %d in reg %s\n", info->vret_arg_reg, mono_arch_regname (gcinfo->ret.reg));
	} else {
		info->vret_arg_reg = -1;
	}

#ifdef DEBUG_AMD64_GSHAREDVT
	printf ("final map:\n");
	for (i = 0; i < map->len; i += 2) {
		printf ("\t[%d] src %x dst %x\n ", 
			i / 2,
			GPOINTER_TO_UINT (g_ptr_array_index (map, i)),
			GPOINTER_TO_UINT (g_ptr_array_index (map, i + 1)));
	}
#endif

	info->vcall_offset = vcall_offset;
	info->map_count = map->len / 2;
	for (i = 0; i < map->len; ++i)
		info->map [i] = GPOINTER_TO_UINT (g_ptr_array_index (map, i));
	g_ptr_array_free (map, TRUE);

	/* Compute return value marshalling */
	if (var_ret) {
		/* Compute return value marshalling */
		switch (cinfo->ret.storage) {
		case ArgInIReg:
			if (!gsharedvt_in || sig->ret->byref) {
				info->ret_marshal = GSHAREDVT_RET_IREGS_1;
			} else {
				MonoType *ret = sig->ret;

				// Unwrap enums
				if (ret->type == MONO_TYPE_VALUETYPE)
					ret = mini_type_get_underlying_type (ret);

				switch (ret->type) {
				case MONO_TYPE_I1:
					info->ret_marshal = GSHAREDVT_RET_I1;
					break;
				case MONO_TYPE_BOOLEAN:
				case MONO_TYPE_U1:
					info->ret_marshal = GSHAREDVT_RET_U1;
					break;
				case MONO_TYPE_I2:
					info->ret_marshal = GSHAREDVT_RET_I2;
					break;
				case MONO_TYPE_CHAR:
				case MONO_TYPE_U2:
					info->ret_marshal = GSHAREDVT_RET_U2;
					break;
				case MONO_TYPE_I4:
					info->ret_marshal = GSHAREDVT_RET_I4;
					break;
				case MONO_TYPE_U4:
					info->ret_marshal = GSHAREDVT_RET_U4;
					break;
				case MONO_TYPE_I:
				case MONO_TYPE_U:
				case MONO_TYPE_PTR:
				case MONO_TYPE_FNPTR:
				case MONO_TYPE_CLASS:
				case MONO_TYPE_OBJECT:
				case MONO_TYPE_SZARRAY:
				case MONO_TYPE_ARRAY:
				case MONO_TYPE_STRING:
				case MONO_TYPE_U8:
				case MONO_TYPE_I8:
					info->ret_marshal = GSHAREDVT_RET_I8;
					break;
				case MONO_TYPE_GENERICINST:
					g_assert (!mono_type_generic_inst_is_valuetype (ret));
					info->ret_marshal = GSHAREDVT_RET_I8;
					break;
				default:
					g_error ("Gsharedvt can't handle dst type [%d]", (int)sig->ret->type);
				}
			}
			break;
		case ArgValuetypeInReg:
			info->ret_marshal = GSHAREDVT_RET_IREGS_1 - 1 + cinfo->ret.nregs;
			g_assert (cinfo->ret.nregs == 1); // ABI supports 2-register return but we do not implement this.
			break;
		case ArgInDoubleSSEReg:
		case ArgInFloatSSEReg:
			info->ret_marshal = GSHAREDVT_RET_R8;
			break;
		case ArgValuetypeAddrInIReg:
			break;
		default:
			g_error ("Can't marshal return of storage [%d] %s", (int)cinfo->ret.storage, storage_name (cinfo->ret.storage));
		}

		if (gsharedvt_in && cinfo->ret.storage != ArgValuetypeAddrInIReg) {
			/* Allocate stack space for the return value */
			info->vret_slot = map_stack_slot (info->stack_usage / sizeof (gpointer));
			info->stack_usage += mono_type_stack_size_internal (normal_sig->ret, NULL, FALSE) + sizeof (gpointer);
		}
		DEBUG_AMD64_GSHAREDVT_PRINT ("RET marshal is %s\n", ret_marshal_name [info->ret_marshal]);
	}

	info->stack_usage = ALIGN_TO (info->stack_usage, MONO_ARCH_FRAME_ALIGNMENT);

	g_free (callee_cinfo);
	g_free (caller_cinfo);

	DEBUG_AMD64_GSHAREDVT_PRINT ("allocated an info at %p stack usage %d\n", info, info->stack_usage);
	return info;
}