Merge pull request #3522 from henricm/fix-csharp-compiler-path-windows
[mono.git] / mono / profiler / proflog.c
index 529d5d675e57f4a545f5e1f5d67c9f6e0cab9f5b..17f43836afdee6caccfd37e4889a97851a61b939 100644 (file)
@@ -15,8 +15,9 @@
 #include "../metadata/metadata-internals.h"
 #include <mono/metadata/profiler.h>
 #include <mono/metadata/threads.h>
-#include <mono/metadata/mono-gc.h>
 #include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/mono-config.h>
+#include <mono/metadata/mono-gc.h>
 #include <mono/metadata/mono-perfcounters.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/assembly.h>
@@ -173,7 +174,12 @@ static MonoLinkedListSet profiler_thread_list;
  * [flags: 4 bytes] file format flags, should be 0 for now
  * [pid: 4 bytes] pid of the profiled process
  * [port: 2 bytes] tcp port for server if != 0
- * [sysid: 2 bytes] operating system and architecture identifier
+ * [args size: 4 bytes] size of args
+ * [args: string] arguments passed to the profiler
+ * [arch size: 4 bytes] size of arch
+ * [arch: string] architecture the profiler is running on
+ * [os size: 4 bytes] size of os
+ * [os: string] operating system the profiler is running on
  *
  * The multiple byte integers are in little-endian format.
  *
@@ -207,7 +213,9 @@ static MonoLinkedListSet profiler_thread_list;
  * [method_base: 8 bytes] base value for MonoMethod pointers
  *
  * event format:
- * [extended info: upper 4 bits] [type: lower 4 bits] [data]*
+ * [extended info: upper 4 bits] [type: lower 4 bits]
+ * [time diff: uleb128] nanoseconds since last timing
+ * [data]*
  * The data that follows depends on type and the extended info.
  * Type is one of the enum values in proflog.h: TYPE_ALLOC, TYPE_GC,
  * TYPE_METADATA, TYPE_METHOD, TYPE_EXCEPTION, TYPE_MONITOR, TYPE_HEAP.
@@ -217,12 +225,12 @@ static MonoLinkedListSet profiler_thread_list;
  *
  * backtrace format:
  * [num: uleb128] number of frames following
- * [frame: sleb128]* num MonoMethod pointers as differences from ptr_base
+ * [frame: sleb128]* mum MonoMethod* as a pointer difference from the last such
+ * pointer or the buffer method_base
  *
  * type alloc format:
  * type: TYPE_ALLOC
  * exinfo: flags: TYPE_ALLOC_BT
- * [time diff: uleb128] nanoseconds since last timing
  * [ptr: sleb128] class as a byte difference from ptr_base
  * [obj: sleb128] object address as a byte difference from obj_base
  * [size: uleb128] size of the object in the heap
@@ -233,7 +241,6 @@ static MonoLinkedListSet profiler_thread_list;
  * exinfo: one of TYPE_GC_EVENT, TYPE_GC_RESIZE, TYPE_GC_MOVE, TYPE_GC_HANDLE_CREATED[_BT],
  * TYPE_GC_HANDLE_DESTROYED[_BT], TYPE_GC_FINALIZE_START, TYPE_GC_FINALIZE_END,
  * TYPE_GC_FINALIZE_OBJECT_START, TYPE_GC_FINALIZE_OBJECT_END
- * [time diff: uleb128] nanoseconds since last timing
  * if exinfo == TYPE_GC_RESIZE
  *     [heap_size: uleb128] new heap size
  * if exinfo == TYPE_GC_EVENT
@@ -261,7 +268,6 @@ static MonoLinkedListSet profiler_thread_list;
  * type metadata format:
  * type: TYPE_METADATA
  * exinfo: one of: TYPE_END_LOAD, TYPE_END_UNLOAD (optional for TYPE_THREAD and TYPE_DOMAIN)
- * [time diff: uleb128] nanoseconds since last timing
  * [mtype: byte] metadata type, one of: TYPE_CLASS, TYPE_IMAGE, TYPE_ASSEMBLY, TYPE_DOMAIN,
  * TYPE_THREAD, TYPE_CONTEXT
  * [pointer: sleb128] pointer of the metadata type depending on mtype
@@ -282,7 +288,6 @@ static MonoLinkedListSet profiler_thread_list;
  * type method format:
  * type: TYPE_METHOD
  * exinfo: one of: TYPE_LEAVE, TYPE_ENTER, TYPE_EXC_LEAVE, TYPE_JIT
- * [time diff: uleb128] nanoseconds since last timing
  * [method: sleb128] MonoMethod* as a pointer difference from the last such
  * pointer or the buffer method_base
  * if exinfo == TYPE_JIT
@@ -290,10 +295,21 @@ static MonoLinkedListSet profiler_thread_list;
  *     [code size: uleb128] size of the generated code
  *     [name: string] full method name
  *
+ * type exception format:
+ * type: TYPE_EXCEPTION
+ * exinfo: TYPE_THROW_BT flag or one of: TYPE_CLAUSE
+ * if exinfo == TYPE_CLAUSE
+ *     [clause type: byte] MonoExceptionEnum enum value
+ *     [clause index: uleb128] index of the current clause
+ *     [method: sleb128] MonoMethod* as a pointer difference from the last such
+ *     pointer or the buffer method_base
+ * else
+ *     [object: sleb128] the exception object as a difference from obj_base
+ *     if exinfo has TYPE_THROW_BT set, a backtrace follows.
+ *
  * type runtime format:
  * type: TYPE_RUNTIME
  * exinfo: one of: TYPE_JITHELPER
- * [time diff: uleb128] nanoseconds since last timing
  * if exinfo == TYPE_JITHELPER
  *     [type: byte] MonoProfilerCodeBufferType enum value
  *     [buffer address: sleb128] pointer to the native code as a diff from ptr_base
@@ -304,7 +320,6 @@ static MonoLinkedListSet profiler_thread_list;
  * type monitor format:
  * type: TYPE_MONITOR
  * exinfo: TYPE_MONITOR_BT flag and one of: MONO_PROFILER_MONITOR_(CONTENTION|FAIL|DONE)
- * [time diff: uleb128] nanoseconds since last timing
  * [object: sleb128] the lock object as a difference from obj_base
  * if exinfo.low3bits == MONO_PROFILER_MONITOR_CONTENTION
  *     If the TYPE_MONITOR_BT flag is set, a backtrace follows.
@@ -312,10 +327,6 @@ static MonoLinkedListSet profiler_thread_list;
  * type heap format
  * type: TYPE_HEAP
  * exinfo: one of TYPE_HEAP_START, TYPE_HEAP_END, TYPE_HEAP_OBJECT, TYPE_HEAP_ROOT
- * if exinfo == TYPE_HEAP_START
- *     [time diff: uleb128] nanoseconds since last timing
- * if exinfo == TYPE_HEAP_END
- *     [time diff: uleb128] nanoseconds since last timing
  * if exinfo == TYPE_HEAP_OBJECT
  *     [object: sleb128] the object as a difference from obj_base
  *     [class: sleb128] the object MonoClass* as a difference from ptr_base
@@ -341,7 +352,6 @@ static MonoLinkedListSet profiler_thread_list;
  * exinfo: one of TYPE_SAMPLE_HIT, TYPE_SAMPLE_USYM, TYPE_SAMPLE_UBIN, TYPE_SAMPLE_COUNTERS_DESC, TYPE_SAMPLE_COUNTERS
  * if exinfo == TYPE_SAMPLE_HIT
  *     [sample_type: byte] type of sample (SAMPLE_*)
- *     [timestamp: uleb128] nanoseconds since startup (note: different from other timestamps!)
  *     [thread: sleb128] thread id as difference from ptr_base
  *     [count: uleb128] number of following instruction addresses
  *     [ip: sleb128]* instruction pointer as difference from ptr_base
@@ -353,7 +363,6 @@ static MonoLinkedListSet profiler_thread_list;
  *     [size: uleb128] symbol size (may be 0 if unknown)
  *     [name: string] symbol name
  * if exinfo == TYPE_SAMPLE_UBIN
- *     [time diff: uleb128] nanoseconds since last timing
  *     [address: sleb128] address where binary has been loaded
  *     [offset: uleb128] file offset of mapping (the same file can be mapped multiple times)
  *     [size: uleb128] memory size
@@ -370,7 +379,6 @@ static MonoLinkedListSet profiler_thread_list;
  *             [variance: byte] variance of counter
  *             [index: uleb128] unique index of counter
  * if exinfo == TYPE_SAMPLE_COUNTERS
- *     [timestamp: uleb128] sampling timestamp
  *     while true:
  *             [index: uleb128] unique index of counter
  *             if index == 0:
@@ -424,7 +432,6 @@ static MonoLinkedListSet profiler_thread_list;
  * type meta format:
  * type: TYPE_META
  * exinfo: one of: TYPE_SYNC_POINT
- * [time diff: uleb128] nanoseconds since last timing
  * if exinfo == TYPE_SYNC_POINT
  *     [type: byte] MonoProfilerSyncPointType enum value
  */
@@ -585,6 +592,7 @@ struct _MonoProfiler {
 #if defined (HAVE_SYS_ZLIB)
        gzFile gzfile;
 #endif
+       char *args;
        uint64_t startup_time;
        int pipe_output;
        int last_gc_gen_started;
@@ -1018,32 +1026,66 @@ write_int64 (char *buf, int64_t value)
        return buf + 8;
 }
 
+static char *
+write_header_string (char *p, const char *str)
+{
+       size_t len = strlen (str) + 1;
+
+       p = write_int32 (p, len);
+       strcpy (p, str);
+
+       return p + len;
+}
+
 static void
 dump_header (MonoProfiler *profiler)
 {
-       char hbuf [128];
+       const char *args = profiler->args;
+       const char *arch = mono_config_get_cpu ();
+       const char *os = mono_config_get_os ();
+
+       char *hbuf = malloc (
+               sizeof (gint32) /* header id */ +
+               sizeof (gint8) /* major version */ +
+               sizeof (gint8) /* minor version */ +
+               sizeof (gint8) /* data version */ +
+               sizeof (gint8) /* word size */ +
+               sizeof (gint64) /* startup time */ +
+               sizeof (gint32) /* timer overhead */ +
+               sizeof (gint32) /* flags */ +
+               sizeof (gint32) /* process id */ +
+               sizeof (gint16) /* command port */ +
+               sizeof (gint32) + strlen (args) + 1 /* arguments */ +
+               sizeof (gint32) + strlen (arch) + 1 /* architecture */ +
+               sizeof (gint32) + strlen (os) + 1 /* operating system */
+       );
        char *p = hbuf;
+
        p = write_int32 (p, LOG_HEADER_ID);
        *p++ = LOG_VERSION_MAJOR;
        *p++ = LOG_VERSION_MINOR;
        *p++ = LOG_DATA_VERSION;
-       *p++ = sizeof (void*);
-       p = write_int64 (p, ((uint64_t)time (NULL)) * 1000); /* startup time */
-       p = write_int32 (p, get_timer_overhead ()); /* timer overhead */
+       *p++ = sizeof (void *);
+       p = write_int64 (p, ((uint64_t) time (NULL)) * 1000);
+       p = write_int32 (p, get_timer_overhead ());
        p = write_int32 (p, 0); /* flags */
-       p = write_int32 (p, process_id ()); /* pid */
-       p = write_int16 (p, profiler->command_port); /* port */
-       p = write_int16 (p, 0); /* opsystem */
+       p = write_int32 (p, process_id ());
+       p = write_int16 (p, profiler->command_port);
+       p = write_header_string (p, args);
+       p = write_header_string (p, arch);
+       p = write_header_string (p, os);
+
 #if defined (HAVE_SYS_ZLIB)
        if (profiler->gzfile) {
                gzwrite (profiler->gzfile, hbuf, p - hbuf);
-       } else {
+       } else
+#endif
+       {
                fwrite (hbuf, p - hbuf, 1, profiler->file);
+               fflush (profiler->file);
        }
-#else
-       fwrite (hbuf, p - hbuf, 1, profiler->file);
-       fflush (profiler->file);
-#endif
+
+       free (hbuf);
 }
 
 static void
@@ -1106,8 +1148,10 @@ dump_buffer (MonoProfiler *profiler, LogBuffer *buf)
 {
        char hbuf [128];
        char *p = hbuf;
+
        if (buf->next)
                dump_buffer (profiler, buf->next);
+
        p = write_int32 (p, BUF_ID);
        p = write_int32 (p, buf->cursor - buf->buf);
        p = write_int64 (p, buf->time_base);
@@ -1115,18 +1159,19 @@ dump_buffer (MonoProfiler *profiler, LogBuffer *buf)
        p = write_int64 (p, buf->obj_base);
        p = write_int64 (p, buf->thread_id);
        p = write_int64 (p, buf->method_base);
+
 #if defined (HAVE_SYS_ZLIB)
        if (profiler->gzfile) {
                gzwrite (profiler->gzfile, hbuf, p - hbuf);
                gzwrite (profiler->gzfile, buf->buf, buf->cursor - buf->buf);
-       } else {
+       } else
 #endif
+       {
                fwrite (hbuf, p - hbuf, 1, profiler->file);
                fwrite (buf->buf, buf->cursor - buf->buf, 1, profiler->file);
                fflush (profiler->file);
-#if defined (HAVE_SYS_ZLIB)
        }
-#endif
+
        free_buffer (buf, buf->size);
 }
 
@@ -1894,7 +1939,7 @@ class_loaded (MonoProfiler *prof, MonoClass *klass, int result)
        if (runtime_inited)
                mono_free (name);
        else
-               free (name);
+               g_free (name);
 
        send_if_needed (prof);
 
@@ -1938,7 +1983,7 @@ class_unloaded (MonoProfiler *prof, MonoClass *klass)
        if (runtime_inited)
                mono_free (name);
        else
-               free (name);
+               g_free (name);
 
        send_if_needed (prof);
 
@@ -2076,7 +2121,7 @@ code_buffer_new (MonoProfiler *prof, void *buffer, int size, MonoProfilerCodeBuf
 static void
 throw_exc (MonoProfiler *prof, MonoObject *object)
 {
-       int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces) ? TYPE_EXCEPTION_BT : 0;
+       int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces) ? TYPE_THROW_BT : 0;
        FrameData data;
 
        if (do_bt)
@@ -2517,7 +2562,7 @@ add_code_pointer (uintptr_t ip)
                                add_code_page (n, size_code_pages, code_pages [i]);
                }
                if (code_pages)
-                       free (code_pages);
+                       g_free (code_pages);
                code_pages = n;
        }
        num_code_pages += add_code_page (code_pages, size_code_pages, ip & CPAGE_MASK);
@@ -2697,7 +2742,7 @@ elf_dl_callback (struct dl_phdr_info *info, size_t size, void *data)
                        filename = buf;
                }
        }
-       obj = calloc (sizeof (BinaryObject), 1);
+       obj = g_calloc (sizeof (BinaryObject), 1);
        obj->addr = (void*)info->dlpi_addr;
        obj->name = pstrdup (filename);
        obj->next = prof->binary_objects;
@@ -2771,7 +2816,7 @@ symbol_for (uintptr_t code)
                names = backtrace_symbols (&ip, 1);
                if (names) {
                        const char* p = names [0];
-                       free (names);
+                       g_free (names);
                        return p;
                }
                */
@@ -3098,13 +3143,13 @@ setup_perf_event (void)
        int i, count = 0;
        mmap_mask = num_pages * getpagesize () - 1;
        num_perf = mono_cpu_count ();
-       perf_data = calloc (num_perf, sizeof (PerfData));
+       perf_data = g_calloc (num_perf, sizeof (PerfData));
        for (i = 0; i < num_perf; ++i) {
                count += setup_perf_event_for_cpu (perf_data + i, i);
        }
        if (count)
                return 1;
-       free (perf_data);
+       g_free (perf_data);
        perf_data = NULL;
        return 0;
 }
@@ -3142,7 +3187,7 @@ counters_add_agent (MonoCounter *counter)
                if (agent->counter == counter) {
                        agent->value_size = 0;
                        if (agent->value) {
-                               free (agent->value);
+                               g_free (agent->value);
                                agent->value = NULL;
                        }
                        mono_os_mutex_unlock (&counters_mutex);
@@ -3271,7 +3316,7 @@ counters_sample (MonoProfiler *profiler, uint64_t timestamp)
        counters_emit (profiler);
 
        buffer_size = 8;
-       buffer = calloc (1, buffer_size);
+       buffer = g_calloc (1, buffer_size);
 
        mono_os_mutex_lock (&counters_mutex);
 
@@ -3307,7 +3352,7 @@ counters_sample (MonoProfiler *profiler, uint64_t timestamp)
                        continue; // FIXME error
                } else if (size > buffer_size) {
                        buffer_size = size;
-                       buffer = realloc (buffer, buffer_size);
+                       buffer = g_realloc (buffer, buffer_size);
                }
 
                memset (buffer, 0, buffer_size);
@@ -3318,7 +3363,7 @@ counters_sample (MonoProfiler *profiler, uint64_t timestamp)
                type = mono_counter_get_type (counter);
 
                if (!agent->value) {
-                       agent->value = calloc (1, size);
+                       agent->value = g_calloc (1, size);
                        agent->value_size = size;
                } else {
                        if (type == MONO_COUNTER_STRING) {
@@ -3368,14 +3413,14 @@ counters_sample (MonoProfiler *profiler, uint64_t timestamp)
                }
 
                if (type == MONO_COUNTER_STRING && size > agent->value_size) {
-                       agent->value = realloc (agent->value, size);
+                       agent->value = g_realloc (agent->value, size);
                        agent->value_size = size;
                }
 
                if (size > 0)
                        memcpy (agent->value, buffer, size);
        }
-       free (buffer);
+       g_free (buffer);
 
        emit_value (logbuffer, 0);
 
@@ -4263,6 +4308,15 @@ log_shutdown (MonoProfiler *prof)
 
        cleanup_reusable_samples (prof);
 
+       /*
+        * Pump the entire hazard free queue to make sure that anything we allocated
+        * in the profiler will be freed. If we don't do this, the runtime could get
+        * around to freeing some items after the profiler has been unloaded, which
+        * would mean calling into functions in the profiler library, leading to a
+        * crash.
+        */
+       mono_thread_hazardous_try_free_all ();
+
        g_assert (!InterlockedRead (&buffer_rwlock_count) && "Why is the reader count still non-zero?");
        g_assert (!InterlockedReadPointer (&buffer_rwlock_exclusive) && "Why does someone still hold the exclusive lock?");
 
@@ -4296,7 +4350,8 @@ log_shutdown (MonoProfiler *prof)
 
        PROF_TLS_FREE ();
 
-       free (prof);
+       g_free (prof->args);
+       g_free (prof);
 }
 
 static char*
@@ -4370,7 +4425,6 @@ helper_thread (void* arg)
        int command_socket;
        int len;
        char buf [64];
-       MonoThread *thread = NULL;
 
        mono_threads_attach_tools_thread ();
        mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler helper");
@@ -4430,8 +4484,6 @@ helper_thread (void* arg)
                if (FD_ISSET (prof->pipes [0], &rfds)) {
                        char c;
                        read (prof->pipes [0], &c, 1);
-                       if (thread)
-                               mono_thread_detach (thread);
                        if (do_debug)
                                fprintf (stderr, "helper shutdown\n");
 #if USE_PERF_EVENTS
@@ -4471,18 +4523,10 @@ helper_thread (void* arg)
                                continue;
                        }
                        buf [len] = 0;
-                       if (strcmp (buf, "heapshot\n") == 0) {
+                       if (strcmp (buf, "heapshot\n") == 0 && hs_mode_ondemand) {
+                               // Rely on the finalization callbacks invoking process_requests ().
                                heapshot_requested = 1;
-                               //fprintf (stderr, "perform heapshot\n");
-                               if (InterlockedRead (&runtime_inited) && !thread) {
-                                       thread = mono_thread_attach (mono_get_root_domain ());
-                                       /*fprintf (stderr, "attached\n");*/
-                               }
-                               if (thread) {
-                                       process_requests (prof);
-                                       mono_thread_detach (thread);
-                                       thread = NULL;
-                               }
+                               mono_gc_finalize_notify ();
                        }
                        continue;
                }
@@ -4616,7 +4660,7 @@ handle_writer_queue_entry (MonoProfiler *prof)
                        mono_free (name);
 
                free_info:
-                       free (info);
+                       g_free (info);
                }
 
                g_ptr_array_free (entry->methods, TRUE);
@@ -4820,13 +4864,14 @@ runtime_initialized (MonoProfiler *profiler)
 }
 
 static MonoProfiler*
-create_profiler (const char *filename, GPtrArray *filters)
+create_profiler (const char *args, const char *filename, GPtrArray *filters)
 {
        MonoProfiler *prof;
        char *nf;
        int force_delete = 0;
        prof = (MonoProfiler *)calloc (1, sizeof (MonoProfiler));
 
+       prof->args = pstrdup (args);
        prof->command_port = command_port;
        if (filename && *filename == '-') {
                force_delete = 1;
@@ -4844,7 +4889,7 @@ create_profiler (const char *filename, GPtrArray *filters)
                        int s = strlen (nf) + 32;
                        char *p = (char *)malloc (s);
                        snprintf (p, s, "|mprof-report '--out=%s' -", nf);
-                       free (nf);
+                       g_free (nf);
                        nf = p;
                }
        }
@@ -4868,7 +4913,7 @@ create_profiler (const char *filename, GPtrArray *filters)
                prof->gzfile = gzdopen (fileno (prof->file), "wb");
 #endif
 #if USE_PERF_EVENTS
-       if (sample_type && !do_mono_sample)
+       if (sample_type && sample_freq && !do_mono_sample)
                need_helper_thread = setup_perf_event ();
        if (!perf_data) {
                /* FIXME: warn if different freq or sample type */
@@ -4890,7 +4935,7 @@ create_profiler (const char *filename, GPtrArray *filters)
 
        // FIXME: We should free this stuff too.
        mono_lock_free_allocator_init_size_class (&prof->sample_size_class, SAMPLE_SLOT_SIZE (num_frames), SAMPLE_BLOCK_SIZE);
-       mono_lock_free_allocator_init_allocator (&prof->sample_allocator, &prof->sample_size_class);
+       mono_lock_free_allocator_init_allocator (&prof->sample_allocator, &prof->sample_size_class, MONO_MEM_ACCOUNT_PROFILER);
 
        mono_lock_free_queue_init (&prof->sample_reuse_queue);
 
@@ -4907,7 +4952,7 @@ create_profiler (const char *filename, GPtrArray *filters)
 
        // FIXME: We should free this stuff too.
        mono_lock_free_allocator_init_size_class (&prof->writer_entry_size_class, sizeof (WriterQueueEntry), WRITER_ENTRY_BLOCK_SIZE);
-       mono_lock_free_allocator_init_allocator (&prof->writer_entry_allocator, &prof->writer_entry_size_class);
+       mono_lock_free_allocator_init_allocator (&prof->writer_entry_allocator, &prof->writer_entry_size_class, MONO_MEM_ACCOUNT_PROFILER);
 
        mono_lock_free_queue_init (&prof->writer_queue);
        mono_os_sem_init (&prof->writer_queue_sem, 0);
@@ -5029,7 +5074,7 @@ set_sample_mode (char* val, int allow_empty)
        if (strcmp (val, "mono") == 0) {
                do_mono_sample = 1;
                sample_type = SAMPLE_CYCLES;
-               free (val);
+               g_free (val);
                return;
        }
        for (smode = sample_modes; smode->name; smode++) {
@@ -5052,7 +5097,7 @@ set_sample_mode (char* val, int allow_empty)
        } else {
                sample_freq = 100;
        }
-       free (val);
+       g_free (val);
 }
 
 static void
@@ -5064,7 +5109,7 @@ set_hsmode (char* val, int allow_empty)
                return;
        if (strcmp (val, "ondemand") == 0) {
                hs_mode_ondemand = 1;
-               free (val);
+               g_free (val);
                return;
        }
        count = strtoul (val, &end, 10);
@@ -5076,7 +5121,7 @@ set_hsmode (char* val, int allow_empty)
                hs_mode_gc = count;
        else
                usage (1);
-       free (val);
+       g_free (val);
 }
 
 /*
@@ -5161,7 +5206,7 @@ mono_profiler_startup (const char *desc)
                                fast_time = 2;
                        else
                                usage (1);
-                       free (val);
+                       g_free (val);
                        continue;
                }
                if ((opt = match_option (p, "report", NULL)) != p) {
@@ -5211,7 +5256,7 @@ mono_profiler_startup (const char *desc)
                if ((opt = match_option (p, "port", &val)) != p) {
                        char *end;
                        command_port = strtoul (val, &end, 10);
-                       free (val);
+                       g_free (val);
                        continue;
                }
                if ((opt = match_option (p, "maxframes", &val)) != p) {
@@ -5219,7 +5264,7 @@ mono_profiler_startup (const char *desc)
                        num_frames = strtoul (val, &end, 10);
                        if (num_frames > MAX_FRAMES)
                                num_frames = MAX_FRAMES;
-                       free (val);
+                       g_free (val);
                        notraces = num_frames == 0;
                        continue;
                }
@@ -5228,13 +5273,13 @@ mono_profiler_startup (const char *desc)
                        max_allocated_sample_hits = strtoul (val, &end, 10);
                        if (!max_allocated_sample_hits)
                                max_allocated_sample_hits = G_MAXINT32;
-                       free (val);
+                       g_free (val);
                        continue;
                }
                if ((opt = match_option (p, "calldepth", &val)) != p) {
                        char *end;
                        max_call_depth = strtoul (val, &end, 10);
-                       free (val);
+                       g_free (val);
                        continue;
                }
                if ((opt = match_option (p, "counters", NULL)) != p) {
@@ -5306,7 +5351,7 @@ mono_profiler_startup (const char *desc)
 
        PROF_TLS_INIT ();
 
-       prof = create_profiler (filename, filters);
+       prof = create_profiler (desc, filename, filters);
        if (!prof) {
                PROF_TLS_FREE ();
                return;
@@ -5339,7 +5384,7 @@ mono_profiler_startup (const char *desc)
        if (do_coverage)
                mono_profiler_install_coverage_filter (coverage_filter);
 
-       if (do_mono_sample && sample_type == SAMPLE_CYCLES && !only_counters) {
+       if (do_mono_sample && sample_type == SAMPLE_CYCLES && sample_freq && !only_counters) {
                events |= MONO_PROFILE_STATISTICAL;
                mono_profiler_set_statistical_mode (sampling_mode, sample_freq);
                mono_profiler_install_statistical (mono_sample_hit);