sre-save.c \
custom-attrs.c \
fdhandle.h \
- fdhandle.c
+ fdhandle.c \
+ callspec.h \
+ callspec.c
# These source files have compile time dependencies on GC code
gc_dependent_sources = \
--- /dev/null
+/**
+ * \file
+ * Call specification facilities for the Mono Runtime.
+ *
+ * Author:
+ * Paolo Molaro (lupus@ximian.com)
+ * Dietmar Maurer (dietmar@ximian.com)
+ *
+ * (C) 2002 Ximian, Inc.
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full
+ * license information.
+ */
+#include "metadata.h"
+#include "callspec.h"
+#include "assembly.h"
+#include "class-internals.h"
+#include "debug-helpers.h"
+
+static MonoAssembly *prog_assembly;
+
+gboolean
+mono_callspec_eval_exception (MonoClass *klass, MonoCallSpec *spec)
+{
+ int include = 0;
+ int i;
+
+ if (!klass)
+ return FALSE;
+
+ for (i = 0; i < spec->len; i++) {
+ MonoTraceOperation *op = &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_callspec_eval (MonoMethod *method, const MonoCallSpec *spec)
+{
+ int include = 0;
+ int i;
+
+ for (i = 0; i < spec->len; i++) {
+ MonoTraceOperation *op = &spec->ops[i];
+ int inc = 0;
+
+ switch (op->op) {
+ case MONO_TRACEOP_ALL:
+ inc = 1;
+ break;
+ case MONO_TRACEOP_PROGRAM:
+ if (prog_assembly &&
+ (method->klass->image ==
+ mono_assembly_get_image (prog_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_CLASS:
+ if (strcmp (method->klass->name_space, op->data) == 0)
+ if (strcmp (method->klass->name, op->data2) ==
+ 0)
+ inc = 1;
+ break;
+ case MONO_TRACEOP_ASSEMBLY:
+ if (strcmp (mono_image_get_name (method->klass->image),
+ op->data) == 0)
+ inc = 1;
+ break;
+ case MONO_TRACEOP_NAMESPACE:
+ if (strcmp (method->klass->name_space, op->data) == 0)
+ inc = 1;
+ break;
+ case MONO_TRACEOP_EXCEPTION:
+ break;
+ }
+ if (op->exclude) {
+ if (inc)
+ include = 0;
+ } else if (inc) {
+ include = 1;
+ }
+ }
+ return include;
+}
+
+static int is_filenamechar (char p)
+{
+ if (p >= 'A' && p <= 'Z')
+ return TRUE;
+ if (p >= 'a' && p <= 'z')
+ return TRUE;
+ if (p >= '0' && p <= '9')
+ return TRUE;
+ if (p == '.' || p == ':' || p == '_' || p == '-' || p == '`')
+ return TRUE;
+ return FALSE;
+}
+
+static char *get_string (char **in)
+{
+ char *start = *in;
+ char *p = *in;
+ while (is_filenamechar (*p)) {
+ p++;
+ }
+ size_t len = p - start;
+ char *ret = (char *)g_malloc (len + 1);
+ memcpy (ret, start, len);
+ ret [len] = 0;
+ *in = p;
+ return ret;
+}
+
+enum Token {
+ TOKEN_METHOD,
+ TOKEN_CLASS,
+ TOKEN_ALL,
+ TOKEN_PROGRAM,
+ TOKEN_EXCEPTION,
+ TOKEN_NAMESPACE,
+ TOKEN_WRAPPER,
+ TOKEN_STRING,
+ TOKEN_EXCLUDE,
+ TOKEN_DISABLED,
+ TOKEN_SEPARATOR,
+ TOKEN_END,
+ TOKEN_ERROR
+};
+
+static int get_token (char **in, char **extra, char **errstr)
+{
+ char *p = *in;
+ while (p[0] == '+')
+ p++;
+
+ *extra = NULL;
+
+ if (p[0] == '\0') {
+ *in = p;
+ return TOKEN_END;
+ }
+ if (p[0] == 'M' && p[1] == ':') {
+ p += 2;
+ *extra = get_string (&p);
+ *in = p;
+ return TOKEN_METHOD;
+ }
+ if (p[0] == 'N' && p[1] == ':') {
+ p += 2;
+ *extra = get_string (&p);
+ *in = p;
+ return TOKEN_NAMESPACE;
+ }
+ if (p[0] == 'T' && p[1] == ':') {
+ p += 2;
+ *extra = get_string (&p);
+ *in = p;
+ return TOKEN_CLASS;
+ }
+ if (p[0] == 'E' && p[1] == ':') {
+ p += 2;
+ *extra = get_string (&p);
+ *in = p;
+ return TOKEN_EXCEPTION;
+ }
+ if (*p == '-') {
+ p++;
+ *in = p;
+ return TOKEN_EXCLUDE;
+ }
+ if (is_filenamechar (*p)) {
+ *extra = get_string (&p);
+ *in = p;
+ if (strcmp (*extra, "all") == 0)
+ return TOKEN_ALL;
+ if (strcmp (*extra, "program") == 0)
+ return TOKEN_PROGRAM;
+ if (strcmp (*extra, "wrapper") == 0)
+ return TOKEN_WRAPPER;
+ if (strcmp (*extra, "disabled") == 0)
+ return TOKEN_DISABLED;
+ return TOKEN_STRING;
+ }
+ if (*p == ',') {
+ p++;
+ *in = p;
+ return TOKEN_SEPARATOR;
+ }
+
+ *errstr = g_strdup_printf ("Syntax error at or around '%s'", p);
+ return TOKEN_ERROR;
+}
+
+static int get_spec (char **in, MonoCallSpec *spec, char **errstr)
+{
+ int n = spec->len;
+ char *extra = NULL;
+
+ int token = get_token (in, &extra, errstr);
+ gboolean exclude = FALSE;
+ if (token == TOKEN_EXCLUDE) {
+ exclude = TRUE;
+ token = get_token (in, &extra, errstr);
+ if (token == TOKEN_EXCLUDE || token == TOKEN_DISABLED) {
+ *errstr = g_strdup_printf ("Expecting an expression");
+ token = TOKEN_ERROR;
+ goto out;
+ }
+ }
+ if (token == TOKEN_END || token == TOKEN_SEPARATOR ||
+ token == TOKEN_ERROR)
+ goto out;
+
+ if (token == TOKEN_DISABLED) {
+ spec->enabled = FALSE;
+ goto out;
+ }
+
+ if (token == TOKEN_METHOD) {
+ MonoMethodDesc *desc = mono_method_desc_new (extra, TRUE);
+ if (desc == NULL) {
+ *errstr =
+ g_strdup_printf ("Invalid method name: %s", extra);
+ token = TOKEN_ERROR;
+ goto out;
+ }
+ spec->ops[n].op = MONO_TRACEOP_METHOD;
+ spec->ops[n].data = desc;
+ } else if (token == TOKEN_ALL)
+ spec->ops[n].op = MONO_TRACEOP_ALL;
+ else if (token == TOKEN_PROGRAM)
+ spec->ops[n].op = MONO_TRACEOP_PROGRAM;
+ else if (token == TOKEN_WRAPPER)
+ spec->ops[n].op = MONO_TRACEOP_WRAPPER;
+ else if (token == TOKEN_NAMESPACE) {
+ spec->ops[n].op = MONO_TRACEOP_NAMESPACE;
+ spec->ops[n].data = g_strdup (extra);
+ } else if (token == TOKEN_CLASS || token == TOKEN_EXCEPTION) {
+ char *p = strrchr (extra, '.');
+ if (p) {
+ *p++ = 0;
+ spec->ops[n].data = g_strdup (extra);
+ spec->ops[n].data2 = g_strdup (p);
+ } else {
+ spec->ops[n].data = g_strdup ("");
+ spec->ops[n].data2 = g_strdup (extra);
+ }
+ spec->ops[n].op = token == TOKEN_CLASS ? MONO_TRACEOP_CLASS
+ : MONO_TRACEOP_EXCEPTION;
+ } else if (token == TOKEN_STRING) {
+ spec->ops[n].op = MONO_TRACEOP_ASSEMBLY;
+ spec->ops[n].data = g_strdup (extra);
+ } else {
+ *errstr =
+ g_strdup_printf ("Syntax error in method specification");
+ token = TOKEN_ERROR;
+ goto out;
+ }
+
+ if (exclude)
+ spec->ops[n].exclude = 1;
+
+ spec->len = n + 1;
+ token = TOKEN_SEPARATOR;
+out:
+ if (extra != NULL) {
+ g_free (extra);
+ }
+ return token;
+}
+
+gboolean
+mono_callspec_parse (const char *options, MonoCallSpec *spec, char **errstr)
+{
+ char *p = (char *)options;
+ int size = 1;
+ int token;
+
+ memset (spec, 0, sizeof (*spec));
+ *errstr = NULL;
+
+ spec->enabled = TRUE;
+ if (*p == 0) {
+ spec->len = 1;
+ spec->ops = g_new0 (MonoTraceOperation, 1);
+ spec->ops[0].op = MONO_TRACEOP_ALL;
+ return TRUE;
+ }
+
+ for (p = (char *)options; *p != 0; p++)
+ if (*p == ',')
+ size++;
+
+ spec->ops = g_new0 (MonoTraceOperation, size);
+
+ p = (char *)options;
+
+ while ((token = (get_spec (&p, spec, errstr))) != TOKEN_END) {
+ if (token == TOKEN_ERROR)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void mono_callspec_cleanup (MonoCallSpec *spec)
+{
+ if (spec->ops != NULL) {
+ g_free (spec->ops);
+ }
+ memset (spec, 0, sizeof (*spec));
+}
+
+void
+mono_callspec_set_assembly (MonoAssembly *assembly)
+{
+ prog_assembly = assembly;
+}
--- /dev/null
+/**
+ * \file
+ */
+
+#ifndef __MONO_CALLSPEC_H__
+#define __MONO_CALLSPEC_H__
+#include <glib.h>
+#include <mono/utils/mono-compiler.h>
+
+typedef enum {
+ MONO_TRACEOP_ALL,
+ MONO_TRACEOP_PROGRAM,
+ MONO_TRACEOP_METHOD,
+ MONO_TRACEOP_ASSEMBLY,
+ MONO_TRACEOP_CLASS,
+ MONO_TRACEOP_NAMESPACE,
+ MONO_TRACEOP_EXCEPTION,
+ MONO_TRACEOP_WRAPPER,
+} MonoTraceOpcode;
+
+typedef struct {
+ MonoTraceOpcode op;
+ int exclude;
+ void *data, *data2;
+} MonoTraceOperation;
+
+typedef struct {
+ int len;
+ gboolean enabled;
+ MonoTraceOperation *ops;
+} MonoCallSpec;
+
+G_BEGIN_DECLS
+
+MONO_PROFILER_API gboolean mono_callspec_parse (const char *options,
+ MonoCallSpec *spec,
+ char **errstr);
+MONO_PROFILER_API void mono_callspec_cleanup (MonoCallSpec *spec);
+MONO_PROFILER_API gboolean mono_callspec_eval_exception (MonoClass *klass,
+ MonoCallSpec *spec);
+MONO_PROFILER_API gboolean mono_callspec_eval (MonoMethod *method,
+ const MonoCallSpec *spec);
+void mono_callspec_set_assembly (MonoAssembly *assembly);
+
+G_END_DECLS
+
+#endif /* __MONO_CALLSPEC_H__ */
#include "mono/utils/mono-hwcap.h"
#include "mono/utils/mono-logger-internals.h"
#include "mono/metadata/w32handle.h"
+#include "mono/metadata/callspec.h"
#include "mini.h"
#include "jit.h"
* Need to call this before mini_init () so we can trace methods
* compiled there too.
*/
- mono_jit_trace_calls = mono_trace_parse_options (trace_options);
+ mono_jit_trace_calls = mono_trace_set_options (trace_options);
if (mono_jit_trace_calls == NULL)
exit (1);
}
* Need to call this before mini_init () so we can trace methods
* compiled there too.
*/
- mono_jit_trace_calls = mono_trace_parse_options (trace_options);
+ mono_jit_trace_calls = mono_trace_set_options (trace_options);
if (mono_jit_trace_calls == NULL)
exit (1);
}
return 2;
}
- if (trace_options != NULL)
- mono_trace_set_assembly (assembly);
+ mono_callspec_set_assembly (assembly);
if (mono_compile_aot || action == DO_EXEC) {
const char *error;
gboolean
mono_jit_set_trace_options (const char* options)
{
- MonoTraceSpec *trace_opt = mono_trace_parse_options (options);
+ MonoCallSpec *trace_opt = mono_trace_set_options (options);
if (trace_opt == NULL)
return FALSE;
mono_jit_trace_calls = trace_opt;
#include "mini-llvm.h"
#include "lldb.h"
-MonoTraceSpec *mono_jit_trace_calls;
+MonoCallSpec *mono_jit_trace_calls;
MonoMethodDesc *mono_inject_async_exc_method;
int mono_inject_async_exc_pos;
MonoMethodDesc *mono_break_at_bb_method;
#include "mono/metadata/marshal.h"
#include "mono/metadata/security-manager.h"
#include "mono/metadata/exception.h"
+#include "mono/metadata/callspec.h"
/*
* The mini code should not have any compile time dependencies on the GC being used, so the same object file from mini/
typedef struct MonoBasicBlock MonoBasicBlock;
typedef struct MonoLMF MonoLMF;
typedef struct MonoSpillInfo MonoSpillInfo;
-typedef struct MonoTraceSpec MonoTraceSpec;
-extern MonoTraceSpec *mono_jit_trace_calls;
+extern MonoCallSpec *mono_jit_trace_calls;
extern gboolean mono_break_on_exc;
extern int mono_exc_esp_offset;
extern gboolean mono_compile_aot;
MONO_API gboolean mono_breakpoint_clean_code (guint8 *method_start, guint8 *code, int offset, guint8 *buf, int size);
/* Tracing */
-MonoTraceSpec *mono_trace_parse_options (const char *options);
-void mono_trace_set_assembly (MonoAssembly *assembly);
+MonoCallSpec *mono_trace_set_options (const char *options);
gboolean mono_trace_eval (MonoMethod *method);
extern void
#include <string.h>
#include "mini.h"
#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/assembly.h>
#include <mono/utils/mono-time.h>
#include <mono/utils/mono-memory-model.h>
#include "trace.h"
+#include <mono/metadata/callspec.h>
#if defined (HOST_ANDROID) || (defined (TARGET_IOS) && defined (TARGET_IOS))
# undef printf
# define fprintf(__ignore, ...) g_log ("mono-gc", G_LOG_LEVEL_MESSAGE, __VA_ARGS__)
#endif
-static MonoTraceSpec trace_spec;
+static MonoCallSpec trace_spec;
static volatile gint32 output_lock = 0;
-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)
-{
- int include = 0;
- int i;
-
- for (i = 0; i < trace_spec.len; i++){
- MonoTraceOperation *op = &trace_spec.ops [i];
- int inc = 0;
-
- switch (op->op){
- case MONO_TRACEOP_ALL:
- inc = 1;
- break;
- 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_CLASS:
- if (strcmp (method->klass->name_space, op->data) == 0)
- if (strcmp (method->klass->name, op->data2) == 0)
- inc = 1;
- break;
- case MONO_TRACEOP_ASSEMBLY:
- if (strcmp (mono_image_get_name (method->klass->image), op->data) == 0)
- inc = 1;
- break;
- case MONO_TRACEOP_NAMESPACE:
- if (strcmp (method->klass->name_space, op->data) == 0)
- inc = 1;
- break;
- case MONO_TRACEOP_EXCEPTION:
- break;
- }
- if (op->exclude) {
- if (inc)
- include = 0;
- } else if (inc) {
- include = 1;
- }
- }
- return include;
-}
-
-static int is_filenamechar (char p)
-{
- if (p >= 'A' && p <= 'Z')
- return TRUE;
- if (p >= 'a' && p <= 'z')
- return TRUE;
- if (p >= '0' && p <= '9')
- return TRUE;
- if (p == '.' || p == ':' || p == '_' || p == '-' || p == '`')
- return TRUE;
- return FALSE;
-}
-
-static char *input;
-static char *value;
-
-static void get_string (void)
+gboolean mono_trace_eval_exception (MonoClass *klass)
{
- char *start = input;
- while (is_filenamechar (*input)){
- input++;
- }
- if (value != NULL)
- g_free (value);
- size_t len = input - start;
- value = (char *)g_malloc (len + 1);
- memcpy (value, start, len);
- value [len] = 0;
+ return mono_callspec_eval_exception (klass, &trace_spec);
}
-enum Token {
- TOKEN_METHOD,
- TOKEN_CLASS,
- TOKEN_ALL,
- TOKEN_PROGRAM,
- TOKEN_EXCEPTION,
- TOKEN_NAMESPACE,
- TOKEN_WRAPPER,
- TOKEN_STRING,
- TOKEN_EXCLUDE,
- TOKEN_DISABLED,
- TOKEN_SEPARATOR,
- TOKEN_END,
- TOKEN_ERROR
-};
-
-static int
-get_token (void)
+gboolean mono_trace_eval (MonoMethod *method)
{
- while (input [0] == '+')
- input++;
-
- if (input [0] == '\0') {
- return TOKEN_END;
- }
- if (input [0] == 'M' && input [1] == ':'){
- input += 2;
- get_string ();
- return TOKEN_METHOD;
- }
- if (input [0] == 'N' && input [1] == ':'){
- input += 2;
- get_string ();
- return TOKEN_NAMESPACE;
- }
- if (input [0] == 'T' && input [1] == ':'){
- input += 2;
- 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_SEPARATOR;
- }
-
- fprintf (stderr, "Syntax error at or around '%s'\n", input);
- return TOKEN_ERROR;
+ return mono_callspec_eval (method, &trace_spec);
}
-static void
-cleanup (void)
+MonoCallSpec *mono_trace_set_options (const char *options)
{
- if (value != NULL)
- g_free (value);
-}
-
-static int
-get_spec (int *last)
-{
- int token = get_token ();
- if (token == TOKEN_EXCLUDE){
- token = get_spec (last);
- if (token == TOKEN_EXCLUDE){
- fprintf (stderr, "Expecting an expression");
- return TOKEN_ERROR;
- }
- if (token == TOKEN_ERROR)
- return token;
- trace_spec.ops [(*last)-1].exclude = 1;
- return TOKEN_SEPARATOR;
- }
- if (token == TOKEN_END || token == TOKEN_SEPARATOR || token == TOKEN_ERROR)
- return token;
-
- if (token == TOKEN_METHOD){
- MonoMethodDesc *desc = mono_method_desc_new (value, TRUE);
- if (desc == NULL){
- fprintf (stderr, "Invalid method name: %s\n", value);
- return TOKEN_ERROR;
- }
- trace_spec.ops [*last].op = MONO_TRACEOP_METHOD;
- trace_spec.ops [*last].data = desc;
- } else if (token == TOKEN_ALL)
- 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 || token == TOKEN_EXCEPTION){
- char *p = strrchr (value, '.');
- if (p) {
- *p++ = 0;
- trace_spec.ops [*last].data = g_strdup (value);
- trace_spec.ops [*last].data2 = g_strdup (p);
- }
- else {
- trace_spec.ops [*last].data = g_strdup ("");
- trace_spec.ops [*last].data2 = g_strdup (value);
- }
- 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);
- } else if (token == TOKEN_DISABLED) {
- trace_spec.enabled = FALSE;
- } else {
- fprintf (stderr, "Syntax error in trace option specification\n");
- return TOKEN_ERROR;
+ char *errstr;
+ if (!mono_callspec_parse (options, &trace_spec, &errstr)) {
+ fprintf (stderr, "%s\n", errstr);
+ g_free (errstr);
+ return NULL;
}
- (*last)++;
- return TOKEN_SEPARATOR;
-}
-MonoTraceSpec *
-mono_trace_parse_options (const char *options)
-{
- char *p = (char*)options;
- int size = 1;
- int last_used;
- int token;
-
- trace_spec.enabled = TRUE;
- if (*p == 0){
- trace_spec.len = 1;
- trace_spec.ops = g_new0 (MonoTraceOperation, 1);
- trace_spec.ops [0].op = MONO_TRACEOP_ALL;
- return &trace_spec;
- }
-
- for (p = (char*)options; *p != 0; p++)
- if (*p == ',')
- size++;
-
- trace_spec.ops = g_new0 (MonoTraceOperation, size);
-
- input = (char*)options;
- last_used = 0;
-
- while ((token = (get_spec (&last_used))) != TOKEN_END){
- if (token == TOKEN_ERROR)
- return NULL;
- if (token == TOKEN_SEPARATOR)
- continue;
- }
- trace_spec.len = last_used;
- cleanup ();
return &trace_spec;
}
-void
-mono_trace_set_assembly (MonoAssembly *assembly)
-{
- trace_spec.assembly = assembly;
-}
-
static
#ifdef HAVE_KW_THREAD
__thread
#include <glib.h>
#include "mono/utils/mono-compiler.h"
-typedef enum {
- MONO_TRACEOP_ALL,
- MONO_TRACEOP_PROGRAM,
- MONO_TRACEOP_METHOD,
- MONO_TRACEOP_ASSEMBLY,
- MONO_TRACEOP_CLASS,
- MONO_TRACEOP_NAMESPACE,
- MONO_TRACEOP_EXCEPTION,
- MONO_TRACEOP_WRAPPER,
-} MonoTraceOpcode;
-
-typedef struct {
- MonoTraceOpcode op;
- int exclude;
- void *data, *data2;
-} MonoTraceOperation;
-
-struct MonoTraceSpec {
- int len;
- gboolean enabled;
- MonoTraceOperation *ops;
-
- MonoAssembly *assembly;
-};
-
G_BEGIN_DECLS
void
} else if (match_option (arg, "calldepth", &val)) {
char *end;
config->max_call_depth = strtoul (val, &end, 10);
+ } else if (match_option (arg, "callspec", &val)) {
+ if (!val)
+ val = "";
+ if (val[0] == '\"')
+ ++val;
+ char *spec = g_strdup (val);
+ size_t speclen = strlen (val);
+ if (speclen > 0 && spec[speclen - 1] == '\"')
+ spec[speclen - 1] = '\0';
+ char *errstr;
+ if (!mono_callspec_parse (spec, &config->callspec, &errstr)) {
+ mono_profiler_printf_err (
+ "Could not parse callspec: '%s': %s", spec,
+ errstr);
+ g_free (errstr);
+ mono_callspec_cleanup (&config->callspec);
+ }
+ g_free (spec);
} else if (match_option (arg, "covfilter-file", &val)) {
if (config->cov_filter_files == NULL)
config->cov_filter_files = g_ptr_array_new ();
static MonoProfilerCallInstrumentationFlags
method_filter (MonoProfiler *prof, MonoMethod *method)
{
+ if (log_config.callspec.len > 0 &&
+ !mono_callspec_eval (method, &log_config.callspec))
+ return MONO_PROFILER_CALL_INSTRUMENTATION_NONE;
+
return MONO_PROFILER_CALL_INSTRUMENTATION_ENTER |
MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE |
MONO_PROFILER_CALL_INSTRUMENTATION_TAIL_CALL |
#include <glib.h>
#define MONO_PROFILER_UNSTABLE_GC_ROOTS
#include <mono/metadata/profiler.h>
+#include <mono/metadata/callspec.h>
#define BUF_ID 0x4D504C01
#define LOG_HEADER_ID 0x4D505A01
// Sample mode. Only used at startup.
MonoProfilerSampleMode sampling_mode;
+
+ // Callspec config - which methods are to be instrumented
+ MonoCallSpec callspec;
} ProfilerConfig;
void proflog_parse_args (ProfilerConfig *config, const char *desc);
<ClCompile Include="..\mono\metadata\assembly.c" />\r
<ClCompile Include="..\mono\metadata\attach.c" />\r
<ClCompile Include="..\mono\metadata\boehm-gc.c" />\r
+ <ClCompile Include="..\mono\metadata\callspec.c" />\r
<ClCompile Include="..\mono\metadata\class-accessors.c" />\r
<ClCompile Include="..\mono\metadata\class.c" />\r
<ClCompile Include="..\mono\metadata\cominterop.c" />\r
<ClInclude Include="..\mono\metadata\appdomain-icalls.h" />\r
<ClInclude Include="..\mono\metadata\assembly.h" />\r
<ClInclude Include="..\mono\metadata\attach.h" />\r
+ <ClInclude Include="..\mono\metadata\callspec.h" />\r
<ClInclude Include="..\mono\metadata\cil-coff.h" />\r
<ClInclude Include="..\mono\metadata\class-internals.h" />\r
<ClInclude Include="..\mono\metadata\class.h" />\r