* Dietmar Maurer (dietmar@ximian.com)
*
* (C) 2002 Ximian, Inc.
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
*/
#include <config.h>
#include <mono/utils/mono-time.h>
#include "trace.h"
+#if defined (PLATFORM_ANDROID) || (defined (TARGET_IOS) && defined (TARGET_IOS))
+# undef printf
+# define printf(...) g_log("mono", G_LOG_LEVEL_MESSAGE, __VA_ARGS__)
+# undef fprintf
+# define fprintf(__ignore, ...) g_log ("mono-gc", G_LOG_LEVEL_MESSAGE, __VA_ARGS__)
+#endif
+
+#ifdef __GNUC__
+
+#define RETURN_ADDRESS_N(N) (__builtin_extract_return_addr (__builtin_return_address (N)))
+#define RETURN_ADDRESS() RETURN_ADDRESS_N(0)
+
+#elif defined(_MSC_VER)
+
+#include <intrin.h>
+#pragma intrinsic(_ReturnAddress)
+
+#define RETURN_ADDRESS() _ReturnAddress()
+#define RETURN_ADDRESS_N(N) NULL
+
+#else
+
+#error "Missing return address intrinsics implementation"
+
+#endif
+
static MonoTraceSpec trace_spec;
+gboolean
+mono_trace_eval_exception (MonoClass *klass)
+{
+ int include = 0;
+ int i;
+
+ if (!klass)
+ return FALSE;
+
+ for (i = 0; i < trace_spec.len; i++) {
+ MonoTraceOperation *op = &trace_spec.ops [i];
+ int inc = 0;
+
+ switch (op->op){
+ case MONO_TRACEOP_EXCEPTION:
+ if (strcmp ("", op->data) == 0 && strcmp ("all", op->data2) == 0)
+ inc = 1;
+ else if (strcmp ("", op->data) == 0 || strcmp (klass->name_space, op->data) == 0)
+ if (strcmp (klass->name, op->data2) == 0)
+ inc = 1;
+ break;
+ default:
+ break;
+ }
+ if (op->exclude){
+ if (inc)
+ include = 0;
+ } else if (inc)
+ include = 1;
+ }
+
+ return include;
+}
+
gboolean
mono_trace_eval (MonoMethod *method)
{
case MONO_TRACEOP_PROGRAM:
if (trace_spec.assembly && (method->klass->image == mono_assembly_get_image (trace_spec.assembly)))
inc = 1; break;
+ case MONO_TRACEOP_WRAPPER:
+ if ((method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) ||
+ (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE))
+ inc = 1; break;
case MONO_TRACEOP_METHOD:
if (mono_method_desc_full_match ((MonoMethodDesc *) op->data, method))
inc = 1; break;
case MONO_TRACEOP_NAMESPACE:
if (strcmp (method->klass->name_space, op->data) == 0)
inc = 1;
+ case MONO_TRACEOP_EXCEPTION:
+ break;
}
if (op->exclude){
if (inc)
TOKEN_CLASS,
TOKEN_ALL,
TOKEN_PROGRAM,
+ TOKEN_EXCEPTION,
TOKEN_NAMESPACE,
+ TOKEN_WRAPPER,
TOKEN_STRING,
TOKEN_EXCLUDE,
TOKEN_DISABLED,
static int
get_token (void)
{
+ while (input [0] == '+')
+ input++;
+
if (input [0] == '\0') {
return TOKEN_END;
}
get_string ();
return TOKEN_CLASS;
}
+ if (input [0] == 'E' && input [1] == ':'){
+ input += 2;
+ get_string ();
+ return TOKEN_EXCEPTION;
+ }
+ if (*input == '-'){
+ input++;
+ return TOKEN_EXCLUDE;
+ }
if (is_filenamechar (*input)){
get_string ();
if (strcmp (value, "all") == 0)
return TOKEN_ALL;
if (strcmp (value, "program") == 0)
return TOKEN_PROGRAM;
+ if (strcmp (value, "wrapper") == 0)
+ return TOKEN_WRAPPER;
if (strcmp (value, "disabled") == 0)
return TOKEN_DISABLED;
return TOKEN_STRING;
}
- if (*input == '-'){
- input++;
- return TOKEN_EXCLUDE;
- }
if (*input == ','){
input++;
return TOKEN_SEPARATOR;
trace_spec.ops [*last].op = MONO_TRACEOP_ALL;
else if (token == TOKEN_PROGRAM)
trace_spec.ops [*last].op = MONO_TRACEOP_PROGRAM;
+ else if (token == TOKEN_WRAPPER)
+ trace_spec.ops [*last].op = MONO_TRACEOP_WRAPPER;
else if (token == TOKEN_NAMESPACE){
trace_spec.ops [*last].op = MONO_TRACEOP_NAMESPACE;
trace_spec.ops [*last].data = g_strdup (value);
- } else if (token == TOKEN_CLASS){
+ } else if (token == TOKEN_CLASS || token == TOKEN_EXCEPTION){
char *p = strrchr (value, '.');
if (p) {
*p++ = 0;
trace_spec.ops [*last].data = g_strdup ("");
trace_spec.ops [*last].data2 = g_strdup (value);
}
- trace_spec.ops [*last].op = MONO_TRACEOP_CLASS;
+ trace_spec.ops [*last].op = token == TOKEN_CLASS ? MONO_TRACEOP_CLASS : MONO_TRACEOP_EXCEPTION;
} else if (token == TOKEN_STRING){
trace_spec.ops [*last].op = MONO_TRACEOP_ASSEMBLY;
trace_spec.ops [*last].data = g_strdup (value);
}
static void indent (int diff) {
- int v;
if (diff < 0)
indent_level += diff;
- v = indent_level;
if (start_time == 0)
start_time = mono_100ns_ticks ();
printf ("[%p: %.5f %d] ", (void*)GetCurrentThreadId (), seconds_since_start (), indent_level);
MonoJitArgumentInfo *arg_info;
MonoMethodSignature *sig;
char *fname;
+ MonoGenericSharingContext *gsctx = NULL;
if (!trace_spec.enabled)
return;
g_free (fname);
if (!ebp) {
- printf (") ip: %p\n", __builtin_return_address (1));
+ printf (") ip: %p\n", RETURN_ADDRESS_N (1));
return;
}
arg_info = alloca (sizeof (MonoJitArgumentInfo) * (sig->param_count + 1));
- mono_arch_get_argument_info (sig, sig->param_count, arg_info);
+ if (method->is_inflated) {
+ /* FIXME: Might be better to pass the ji itself */
+ MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), RETURN_ADDRESS (), NULL);
+ if (ji) {
+ gsctx = mono_jit_info_get_generic_sharing_context (ji);
+ if (gsctx && (gsctx->var_is_vt || gsctx->mvar_is_vt)) {
+ /* Needs a ctx to get precise method */
+ printf (") <gsharedvt>\n");
+ return;
+ }
+ }
+ }
+
+ mono_arch_get_argument_info (gsctx, sig, sig->param_count, arg_info);
if (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret)) {
g_assert (!mono_method_signature (method)->ret->byref);
MonoType *type;
char *fname;
va_list ap;
+ MonoGenericSharingContext *gsctx;
if (!trace_spec.enabled)
return;
printf ("LEAVE: %s", fname);
g_free (fname);
+ if (method->is_inflated) {
+ /* FIXME: Might be better to pass the ji itself */
+ MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), RETURN_ADDRESS (), NULL);
+ if (ji) {
+ gsctx = mono_jit_info_get_generic_sharing_context (ji);
+ if (gsctx && (gsctx->var_is_vt || gsctx->mvar_is_vt)) {
+ /* Needs a ctx to get precise method */
+ printf (") <gsharedvt>\n");
+ return;
+ }
+ }
+ }
+
type = mono_method_signature (method)->ret;
handle_enum:
case MONO_TYPE_R4:
case MONO_TYPE_R8: {
double f = va_arg (ap, double);
- printf ("FP=%f\n", f);
+ printf ("FP=%f", f);
break;
}
case MONO_TYPE_VALUETYPE:
printf ("(unknown return type %x)", mono_method_signature (method)->ret->type);
}
- //printf (" ip: %p\n", __builtin_return_address (1));
+ //printf (" ip: %p\n", RETURN_ADDRESS_N (1));
printf ("\n");
fflush (stdout);
}
{
return trace_spec.enabled;
}
-