[profiler] log profiler: limit method instrumentation to selected methods (#5517)
[mono.git] / mono / profiler / log.c
1 /*
2  * log.c: mono log profiler
3  *
4  * Authors:
5  *   Paolo Molaro (lupus@ximian.com)
6  *   Alex Rønne Petersen (alexrp@xamarin.com)
7  *
8  * Copyright 2010 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
10  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
11  */
12
13 #include <config.h>
14 #include <mono/metadata/assembly.h>
15 #include <mono/metadata/class-internals.h>
16 #include <mono/metadata/debug-helpers.h>
17 #include <mono/metadata/loader.h>
18 #include <mono/metadata/metadata-internals.h>
19 #include <mono/metadata/mono-config.h>
20 #include <mono/metadata/mono-gc.h>
21 #include <mono/metadata/mono-perfcounters.h>
22 #include <mono/metadata/tabledefs.h>
23 #include <mono/utils/atomic.h>
24 #include <mono/utils/hazard-pointer.h>
25 #include <mono/utils/lock-free-alloc.h>
26 #include <mono/utils/lock-free-queue.h>
27 #include <mono/utils/mono-conc-hashtable.h>
28 #include <mono/utils/mono-coop-mutex.h>
29 #include <mono/utils/mono-counters.h>
30 #include <mono/utils/mono-logger-internals.h>
31 #include <mono/utils/mono-linked-list-set.h>
32 #include <mono/utils/mono-membar.h>
33 #include <mono/utils/mono-mmap.h>
34 #include <mono/utils/mono-os-mutex.h>
35 #include <mono/utils/mono-os-semaphore.h>
36 #include <mono/utils/mono-threads.h>
37 #include <mono/utils/mono-threads-api.h>
38 #include "log.h"
39
40 #ifdef HAVE_DLFCN_H
41 #include <dlfcn.h>
42 #endif
43 #include <fcntl.h>
44 #ifdef HAVE_LINK_H
45 #include <link.h>
46 #endif
47 #ifdef HAVE_UNISTD_H
48 #include <unistd.h>
49 #endif
50 #if defined(__APPLE__)
51 #include <mach/mach_time.h>
52 #endif
53 #include <netinet/in.h>
54 #ifdef HAVE_SYS_MMAN_H
55 #include <sys/mman.h>
56 #endif
57 #include <sys/socket.h>
58 #if defined (HAVE_SYS_ZLIB)
59 #include <zlib.h>
60 #endif
61
62 // Statistics for internal profiler data structures.
63 static gint32 sample_allocations_ctr,
64               buffer_allocations_ctr;
65
66 // Statistics for profiler events.
67 static gint32 sync_points_ctr,
68               heap_objects_ctr,
69               heap_starts_ctr,
70               heap_ends_ctr,
71               heap_roots_ctr,
72               gc_events_ctr,
73               gc_resizes_ctr,
74               gc_allocs_ctr,
75               gc_moves_ctr,
76               gc_handle_creations_ctr,
77               gc_handle_deletions_ctr,
78               finalize_begins_ctr,
79               finalize_ends_ctr,
80               finalize_object_begins_ctr,
81               finalize_object_ends_ctr,
82               image_loads_ctr,
83               image_unloads_ctr,
84               assembly_loads_ctr,
85               assembly_unloads_ctr,
86               class_loads_ctr,
87               class_unloads_ctr,
88               method_entries_ctr,
89               method_exits_ctr,
90               method_exception_exits_ctr,
91               method_jits_ctr,
92               code_buffers_ctr,
93               exception_throws_ctr,
94               exception_clauses_ctr,
95               monitor_events_ctr,
96               thread_starts_ctr,
97               thread_ends_ctr,
98               thread_names_ctr,
99               domain_loads_ctr,
100               domain_unloads_ctr,
101               domain_names_ctr,
102               context_loads_ctr,
103               context_unloads_ctr,
104               sample_ubins_ctr,
105               sample_usyms_ctr,
106               sample_hits_ctr,
107               counter_descriptors_ctr,
108               counter_samples_ctr,
109               perfcounter_descriptors_ctr,
110               perfcounter_samples_ctr,
111               coverage_methods_ctr,
112               coverage_statements_ctr,
113               coverage_classes_ctr,
114               coverage_assemblies_ctr;
115
116 // Pending data to be written to the log, for a single thread.
117 // Threads periodically flush their own LogBuffers by calling safe_send
118 typedef struct _LogBuffer LogBuffer;
119 struct _LogBuffer {
120         // Next (older) LogBuffer in processing queue
121         LogBuffer *next;
122
123         uint64_t time_base;
124         uint64_t last_time;
125         uintptr_t ptr_base;
126         uintptr_t method_base;
127         uintptr_t last_method;
128         uintptr_t obj_base;
129         uintptr_t thread_id;
130
131         // Bytes allocated for this LogBuffer
132         int size;
133
134         // Start of currently unused space in buffer
135         unsigned char* cursor;
136
137         // Pointer to start-of-structure-plus-size (for convenience)
138         unsigned char* buf_end;
139
140         // Start of data in buffer. Contents follow "buffer format" described above.
141         unsigned char buf [1];
142 };
143
144 typedef struct {
145         MonoLinkedListSetNode node;
146
147         // Was this thread added to the LLS?
148         gboolean attached;
149
150         // The current log buffer for this thread.
151         LogBuffer *buffer;
152
153         // Methods referenced by events in `buffer`, see `MethodInfo`.
154         GPtrArray *methods;
155
156         // Current call depth for enter/leave events.
157         int call_depth;
158
159         // Indicates whether this thread is currently writing to its `buffer`.
160         gboolean busy;
161
162         // Has this thread written a thread end event to `buffer`?
163         gboolean ended;
164
165         // Stored in `buffer_lock_state` to take the exclusive lock.
166         int small_id;
167 } MonoProfilerThread;
168
169 // Do not use these TLS macros directly unless you know what you're doing.
170
171 #ifdef HOST_WIN32
172
173 #define PROF_TLS_SET(VAL) (TlsSetValue (profiler_tls, (VAL)))
174 #define PROF_TLS_GET() ((MonoProfilerThread *) TlsGetValue (profiler_tls))
175 #define PROF_TLS_INIT() (profiler_tls = TlsAlloc ())
176 #define PROF_TLS_FREE() (TlsFree (profiler_tls))
177
178 static DWORD profiler_tls;
179
180 #elif HAVE_KW_THREAD
181
182 #define PROF_TLS_SET(VAL) (profiler_tls = (VAL))
183 #define PROF_TLS_GET() (profiler_tls)
184 #define PROF_TLS_INIT()
185 #define PROF_TLS_FREE()
186
187 static __thread MonoProfilerThread *profiler_tls;
188
189 #else
190
191 #define PROF_TLS_SET(VAL) (pthread_setspecific (profiler_tls, (VAL)))
192 #define PROF_TLS_GET() ((MonoProfilerThread *) pthread_getspecific (profiler_tls))
193 #define PROF_TLS_INIT() (pthread_key_create (&profiler_tls, NULL))
194 #define PROF_TLS_FREE() (pthread_key_delete (profiler_tls))
195
196 static pthread_key_t profiler_tls;
197
198 #endif
199
200 static uintptr_t
201 thread_id (void)
202 {
203         return (uintptr_t) mono_native_thread_id_get ();
204 }
205
206 static uintptr_t
207 process_id (void)
208 {
209 #ifdef HOST_WIN32
210         return (uintptr_t) GetCurrentProcessId ();
211 #else
212         return (uintptr_t) getpid ();
213 #endif
214 }
215
216 #define ENABLED(EVT) (!!(log_config.effective_mask & (EVT)))
217 #define ENABLE(EVT) do { log_config.effective_mask |= (EVT); } while (0)
218 #define DISABLE(EVT) do { log_config.effective_mask &= ~(EVT); } while (0)
219
220 /*
221  * These macros should be used when writing an event to a log buffer. They
222  * take care of a bunch of stuff that can be repetitive and error-prone, such
223  * as attaching the current thread, acquiring/releasing the buffer lock,
224  * incrementing the event counter, expanding the log buffer, etc. They also
225  * create a scope so that it's harder to leak the LogBuffer pointer, which can
226  * be problematic as the pointer is unstable when the buffer lock isn't
227  * acquired.
228  *
229  * If the calling thread is already attached, these macros will not alter its
230  * attach mode (i.e. whether it's added to the LLS). If the thread is not
231  * attached, init_thread () will be called with add_to_lls = TRUE.
232  */
233
234 #define ENTER_LOG(COUNTER, BUFFER, SIZE) \
235         do { \
236                 MonoProfilerThread *thread__ = get_thread (); \
237                 if (thread__->attached) \
238                         buffer_lock (); \
239                 g_assert (!thread__->busy && "Why are we trying to write a new event while already writing one?"); \
240                 thread__->busy = TRUE; \
241                 InterlockedIncrement ((COUNTER)); \
242                 LogBuffer *BUFFER = ensure_logbuf_unsafe (thread__, (SIZE))
243
244 #define EXIT_LOG_EXPLICIT(SEND) \
245                 thread__->busy = FALSE; \
246                 if ((SEND)) \
247                         send_log_unsafe (TRUE); \
248                 if (thread__->attached) \
249                         buffer_unlock (); \
250         } while (0)
251
252 // Pass these to EXIT_LOG_EXPLICIT () for easier reading.
253 #define DO_SEND TRUE
254 #define NO_SEND FALSE
255
256 #define EXIT_LOG EXIT_LOG_EXPLICIT (DO_SEND)
257
258 typedef struct _BinaryObject BinaryObject;
259 struct _BinaryObject {
260         BinaryObject *next;
261         void *addr;
262         char *name;
263 };
264
265 typedef struct MonoCounterAgent {
266         MonoCounter *counter;
267         // MonoCounterAgent specific data :
268         void *value;
269         size_t value_size;
270         guint32 index;
271         gboolean emitted;
272         struct MonoCounterAgent *next;
273 } MonoCounterAgent;
274
275 typedef struct _PerfCounterAgent PerfCounterAgent;
276 struct _PerfCounterAgent {
277         PerfCounterAgent *next;
278         guint32 index;
279         char *category_name;
280         char *name;
281         gint64 value;
282         gboolean emitted;
283         gboolean updated;
284         gboolean deleted;
285 };
286
287 struct _MonoProfiler {
288         MonoProfilerHandle handle;
289
290         FILE* file;
291 #if defined (HAVE_SYS_ZLIB)
292         gzFile gzfile;
293 #endif
294
295         char *args;
296         uint64_t startup_time;
297         int timer_overhead;
298
299 #ifdef __APPLE__
300         mach_timebase_info_data_t timebase_info;
301 #elif defined (HOST_WIN32)
302         LARGE_INTEGER pcounter_freq;
303 #endif
304
305         int pipe_output;
306         int command_port;
307         int server_socket;
308         int pipes [2];
309
310         MonoLinkedListSet profiler_thread_list;
311         volatile gint32 buffer_lock_state;
312         volatile gint32 buffer_lock_exclusive_intent;
313
314         volatile gint32 runtime_inited;
315         volatile gint32 in_shutdown;
316
317         MonoNativeThreadId helper_thread;
318
319         MonoNativeThreadId writer_thread;
320         volatile gint32 run_writer_thread;
321         MonoLockFreeQueue writer_queue;
322         MonoSemType writer_queue_sem;
323
324         MonoLockFreeAllocSizeClass writer_entry_size_class;
325         MonoLockFreeAllocator writer_entry_allocator;
326
327         MonoConcurrentHashTable *method_table;
328         mono_mutex_t method_table_mutex;
329
330         MonoNativeThreadId dumper_thread;
331         volatile gint32 run_dumper_thread;
332         MonoLockFreeQueue dumper_queue;
333         MonoSemType dumper_queue_sem;
334
335         MonoLockFreeAllocSizeClass sample_size_class;
336         MonoLockFreeAllocator sample_allocator;
337         MonoLockFreeQueue sample_reuse_queue;
338
339         BinaryObject *binary_objects;
340
341         volatile gint32 heapshot_requested;
342         guint64 gc_count;
343         guint64 last_hs_time;
344         gboolean do_heap_walk;
345
346         mono_mutex_t counters_mutex;
347         MonoCounterAgent *counters;
348         PerfCounterAgent *perfcounters;
349         guint32 counters_index;
350
351         mono_mutex_t coverage_mutex;
352         GPtrArray *coverage_data;
353
354         GPtrArray *coverage_filters;
355         MonoConcurrentHashTable *coverage_filtered_classes;
356         MonoConcurrentHashTable *coverage_suppressed_assemblies;
357
358         MonoConcurrentHashTable *coverage_methods;
359         MonoConcurrentHashTable *coverage_assemblies;
360         MonoConcurrentHashTable *coverage_classes;
361
362         MonoConcurrentHashTable *coverage_image_to_methods;
363
364         guint32 coverage_previous_offset;
365         guint32 coverage_method_id;
366
367         MonoCoopMutex api_mutex;
368 };
369
370 static ProfilerConfig log_config;
371 static struct _MonoProfiler log_profiler;
372
373 typedef struct {
374         MonoLockFreeQueueNode node;
375         GPtrArray *methods;
376         LogBuffer *buffer;
377 } WriterQueueEntry;
378
379 #define WRITER_ENTRY_BLOCK_SIZE (mono_pagesize ())
380
381 typedef struct {
382         MonoMethod *method;
383         MonoJitInfo *ji;
384         uint64_t time;
385 } MethodInfo;
386
387 #define TICKS_PER_SEC 1000000000LL
388
389 static uint64_t
390 current_time (void)
391 {
392 #ifdef __APPLE__
393         uint64_t time = mach_absolute_time ();
394
395         time *= log_profiler.timebase_info.numer;
396         time /= log_profiler.timebase_info.denom;
397
398         return time;
399 #elif defined (HOST_WIN32)
400         LARGE_INTEGER value;
401
402         QueryPerformanceCounter (&value);
403
404         return value.QuadPart * TICKS_PER_SEC / log_profiler.pcounter_freq.QuadPart;
405 #elif defined (CLOCK_MONOTONIC)
406         struct timespec tspec;
407
408         clock_gettime (CLOCK_MONOTONIC, &tspec);
409
410         return ((uint64_t) tspec.tv_sec * TICKS_PER_SEC + tspec.tv_nsec);
411 #else
412         struct timeval tv;
413
414         gettimeofday (&tv, NULL);
415
416         return ((uint64_t) tv.tv_sec * TICKS_PER_SEC + tv.tv_usec * 1000);
417 #endif
418 }
419
420 static void
421 init_time (void)
422 {
423 #ifdef __APPLE__
424         mach_timebase_info (&log_profiler.timebase_info);
425 #elif defined (HOST_WIN32)
426         QueryPerformanceFrequency (&log_profiler.pcounter_freq);
427 #endif
428
429         uint64_t time_start = current_time ();
430
431         for (int i = 0; i < 256; ++i)
432                 current_time ();
433
434         uint64_t time_end = current_time ();
435
436         log_profiler.timer_overhead = (time_end - time_start) / 256;
437 }
438
439 static char*
440 pstrdup (const char *s)
441 {
442         int len = strlen (s) + 1;
443         char *p = (char *) g_malloc (len);
444         memcpy (p, s, len);
445         return p;
446 }
447
448 #define BUFFER_SIZE (4096 * 16)
449
450 /* Worst-case size in bytes of a 64-bit value encoded with LEB128. */
451 #define LEB128_SIZE 10
452
453 /* Size of a value encoded as a single byte. */
454 #undef BYTE_SIZE // mach/i386/vm_param.h on OS X defines this to 8, but it isn't used for anything.
455 #define BYTE_SIZE 1
456
457 /* Size in bytes of the event prefix (ID + time). */
458 #define EVENT_SIZE (BYTE_SIZE + LEB128_SIZE)
459
460 static void *
461 alloc_buffer (int size)
462 {
463         return mono_valloc (NULL, size, MONO_MMAP_READ | MONO_MMAP_WRITE | MONO_MMAP_ANON | MONO_MMAP_PRIVATE, MONO_MEM_ACCOUNT_PROFILER);
464 }
465
466 static void
467 free_buffer (void *buf, int size)
468 {
469         mono_vfree (buf, size, MONO_MEM_ACCOUNT_PROFILER);
470 }
471
472 static LogBuffer*
473 create_buffer (uintptr_t tid, int bytes)
474 {
475         LogBuffer* buf = (LogBuffer *) alloc_buffer (MAX (BUFFER_SIZE, bytes));
476
477         InterlockedIncrement (&buffer_allocations_ctr);
478
479         buf->size = BUFFER_SIZE;
480         buf->time_base = current_time ();
481         buf->last_time = buf->time_base;
482         buf->buf_end = (unsigned char *) buf + buf->size;
483         buf->cursor = buf->buf;
484         buf->thread_id = tid;
485
486         return buf;
487 }
488
489 /*
490  * Must be called with the reader lock held if thread is the current thread, or
491  * the exclusive lock if thread is a different thread. However, if thread is
492  * the current thread, and init_thread () was called with add_to_lls = FALSE,
493  * then no locking is necessary.
494  */
495 static void
496 init_buffer_state (MonoProfilerThread *thread)
497 {
498         thread->buffer = create_buffer (thread->node.key, 0);
499         thread->methods = NULL;
500 }
501
502 static void
503 clear_hazard_pointers (MonoThreadHazardPointers *hp)
504 {
505         mono_hazard_pointer_clear (hp, 0);
506         mono_hazard_pointer_clear (hp, 1);
507         mono_hazard_pointer_clear (hp, 2);
508 }
509
510 static MonoProfilerThread *
511 init_thread (gboolean add_to_lls)
512 {
513         MonoProfilerThread *thread = PROF_TLS_GET ();
514
515         /*
516          * Sometimes we may try to initialize a thread twice. One example is the
517          * main thread: We initialize it when setting up the profiler, but we will
518          * also get a thread_start () callback for it. Another example is when
519          * attaching new threads to the runtime: We may get a gc_alloc () callback
520          * for that thread's thread object (where we initialize it), soon followed
521          * by a thread_start () callback.
522          *
523          * These cases are harmless anyhow. Just return if we've already done the
524          * initialization work.
525          */
526         if (thread)
527                 return thread;
528
529         thread = g_malloc (sizeof (MonoProfilerThread));
530         thread->node.key = thread_id ();
531         thread->attached = add_to_lls;
532         thread->call_depth = 0;
533         thread->busy = 0;
534         thread->ended = FALSE;
535
536         init_buffer_state (thread);
537
538         thread->small_id = mono_thread_info_register_small_id ();
539
540         /*
541          * Some internal profiler threads don't need to be cleaned up
542          * by the main thread on shutdown.
543          */
544         if (add_to_lls) {
545                 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
546                 g_assert (mono_lls_insert (&log_profiler.profiler_thread_list, hp, &thread->node) && "Why can't we insert the thread in the LLS?");
547                 clear_hazard_pointers (hp);
548         }
549
550         PROF_TLS_SET (thread);
551
552         return thread;
553 }
554
555 // Only valid if init_thread () was called with add_to_lls = FALSE.
556 static void
557 deinit_thread (MonoProfilerThread *thread)
558 {
559         g_assert (!thread->attached && "Why are we manually freeing an attached thread?");
560
561         g_free (thread);
562         PROF_TLS_SET (NULL);
563 }
564
565 static MonoProfilerThread *
566 get_thread (void)
567 {
568         return init_thread (TRUE);
569 }
570
571 // Only valid if init_thread () was called with add_to_lls = FALSE.
572 static LogBuffer *
573 ensure_logbuf_unsafe (MonoProfilerThread *thread, int bytes)
574 {
575         LogBuffer *old = thread->buffer;
576
577         if (old->cursor + bytes < old->buf_end)
578                 return old;
579
580         LogBuffer *new_ = create_buffer (thread->node.key, bytes);
581         new_->next = old;
582         thread->buffer = new_;
583
584         return new_;
585 }
586
587 /*
588  * This is a reader/writer spin lock of sorts used to protect log buffers.
589  * When a thread modifies its own log buffer, it increments the reader
590  * count. When a thread wants to access log buffers of other threads, it
591  * takes the exclusive lock.
592  *
593  * `buffer_lock_state` holds the reader count in its lower 16 bits, and
594  * the small ID of the thread currently holding the exclusive (writer)
595  * lock in its upper 16 bits. Both can be zero. It's important that the
596  * whole lock state is a single word that can be read/written atomically
597  * to avoid race conditions where there could end up being readers while
598  * the writer lock is held.
599  *
600  * The lock is writer-biased. When a thread wants to take the exclusive
601  * lock, it increments `buffer_lock_exclusive_intent` which will make new
602  * readers spin until it's back to zero, then takes the exclusive lock
603  * once the reader count has reached zero. After releasing the exclusive
604  * lock, it decrements `buffer_lock_exclusive_intent`, which, when it
605  * reaches zero again, allows readers to increment the reader count.
606  *
607  * The writer bias is necessary because we take the exclusive lock in
608  * `gc_event ()` during STW. If the writer bias was not there, and a
609  * program had a large number of threads, STW-induced pauses could be
610  * significantly longer than they have to be. Also, we emit periodic
611  * sync points from the helper thread, which requires taking the
612  * exclusive lock, and we need those to arrive with a reasonably
613  * consistent frequency so that readers don't have to queue up too many
614  * events between sync points.
615  *
616  * The lock does not support recursion.
617  */
618
619 static void
620 buffer_lock (void)
621 {
622         /*
623          * If the thread holding the exclusive lock tries to modify the
624          * reader count, just make it a no-op. This way, we also avoid
625          * invoking the GC safe point macros below, which could break if
626          * done from a thread that is currently the initiator of STW.
627          *
628          * In other words, we rely on the fact that the GC thread takes
629          * the exclusive lock in the gc_event () callback when the world
630          * is about to stop.
631          */
632         if (InterlockedRead (&log_profiler.buffer_lock_state) != get_thread ()->small_id << 16) {
633                 MONO_ENTER_GC_SAFE;
634
635                 gint32 old, new_;
636
637                 do {
638                 restart:
639                         // Hold off if a thread wants to take the exclusive lock.
640                         while (InterlockedRead (&log_profiler.buffer_lock_exclusive_intent))
641                                 mono_thread_info_yield ();
642
643                         old = InterlockedRead (&log_profiler.buffer_lock_state);
644
645                         // Is a thread holding the exclusive lock?
646                         if (old >> 16) {
647                                 mono_thread_info_yield ();
648                                 goto restart;
649                         }
650
651                         new_ = old + 1;
652                 } while (InterlockedCompareExchange (&log_profiler.buffer_lock_state, new_, old) != old);
653
654                 MONO_EXIT_GC_SAFE;
655         }
656
657         mono_memory_barrier ();
658 }
659
660 static void
661 buffer_unlock (void)
662 {
663         mono_memory_barrier ();
664
665         gint32 state = InterlockedRead (&log_profiler.buffer_lock_state);
666
667         // See the comment in buffer_lock ().
668         if (state == PROF_TLS_GET ()->small_id << 16)
669                 return;
670
671         g_assert (state && "Why are we decrementing a zero reader count?");
672         g_assert (!(state >> 16) && "Why is the exclusive lock held?");
673
674         InterlockedDecrement (&log_profiler.buffer_lock_state);
675 }
676
677 static void
678 buffer_lock_excl (void)
679 {
680         gint32 new_ = get_thread ()->small_id << 16;
681
682         g_assert (InterlockedRead (&log_profiler.buffer_lock_state) != new_ && "Why are we taking the exclusive lock twice?");
683
684         InterlockedIncrement (&log_profiler.buffer_lock_exclusive_intent);
685
686         MONO_ENTER_GC_SAFE;
687
688         while (InterlockedCompareExchange (&log_profiler.buffer_lock_state, new_, 0))
689                 mono_thread_info_yield ();
690
691         MONO_EXIT_GC_SAFE;
692
693         mono_memory_barrier ();
694 }
695
696 static void
697 buffer_unlock_excl (void)
698 {
699         mono_memory_barrier ();
700
701         gint32 state = InterlockedRead (&log_profiler.buffer_lock_state);
702         gint32 excl = state >> 16;
703
704         g_assert (excl && "Why is the exclusive lock not held?");
705         g_assert (excl == PROF_TLS_GET ()->small_id && "Why does another thread hold the exclusive lock?");
706         g_assert (!(state & 0xFFFF) && "Why are there readers when the exclusive lock is held?");
707
708         InterlockedWrite (&log_profiler.buffer_lock_state, 0);
709         InterlockedDecrement (&log_profiler.buffer_lock_exclusive_intent);
710 }
711
712 static void
713 encode_uleb128 (uint64_t value, uint8_t *buf, uint8_t **endbuf)
714 {
715         uint8_t *p = buf;
716
717         do {
718                 uint8_t b = value & 0x7f;
719                 value >>= 7;
720
721                 if (value != 0) /* more bytes to come */
722                         b |= 0x80;
723
724                 *p ++ = b;
725         } while (value);
726
727         *endbuf = p;
728 }
729
730 static void
731 encode_sleb128 (intptr_t value, uint8_t *buf, uint8_t **endbuf)
732 {
733         int more = 1;
734         int negative = (value < 0);
735         unsigned int size = sizeof (intptr_t) * 8;
736         uint8_t byte;
737         uint8_t *p = buf;
738
739         while (more) {
740                 byte = value & 0x7f;
741                 value >>= 7;
742
743                 /* the following is unnecessary if the
744                  * implementation of >>= uses an arithmetic rather
745                  * than logical shift for a signed left operand
746                  */
747                 if (negative)
748                         /* sign extend */
749                         value |= - ((intptr_t) 1 <<(size - 7));
750
751                 /* sign bit of byte is second high order bit (0x40) */
752                 if ((value == 0 && !(byte & 0x40)) ||
753                     (value == -1 && (byte & 0x40)))
754                         more = 0;
755                 else
756                         byte |= 0x80;
757
758                 *p ++= byte;
759         }
760
761         *endbuf = p;
762 }
763
764 static void
765 emit_byte (LogBuffer *logbuffer, int value)
766 {
767         logbuffer->cursor [0] = value;
768         logbuffer->cursor++;
769
770         g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
771 }
772
773 static void
774 emit_value (LogBuffer *logbuffer, int value)
775 {
776         encode_uleb128 (value, logbuffer->cursor, &logbuffer->cursor);
777
778         g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
779 }
780
781 static void
782 emit_time (LogBuffer *logbuffer, uint64_t value)
783 {
784         uint64_t tdiff = value - logbuffer->last_time;
785         encode_uleb128 (tdiff, logbuffer->cursor, &logbuffer->cursor);
786         logbuffer->last_time = value;
787
788         g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
789 }
790
791 static void
792 emit_event_time (LogBuffer *logbuffer, int event, uint64_t time)
793 {
794         emit_byte (logbuffer, event);
795         emit_time (logbuffer, time);
796 }
797
798 static void
799 emit_event (LogBuffer *logbuffer, int event)
800 {
801         emit_event_time (logbuffer, event, current_time ());
802 }
803
804 static void
805 emit_svalue (LogBuffer *logbuffer, int64_t value)
806 {
807         encode_sleb128 (value, logbuffer->cursor, &logbuffer->cursor);
808
809         g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
810 }
811
812 static void
813 emit_uvalue (LogBuffer *logbuffer, uint64_t value)
814 {
815         encode_uleb128 (value, logbuffer->cursor, &logbuffer->cursor);
816
817         g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
818 }
819
820 static void
821 emit_ptr (LogBuffer *logbuffer, const void *ptr)
822 {
823         if (!logbuffer->ptr_base)
824                 logbuffer->ptr_base = (uintptr_t) ptr;
825
826         emit_svalue (logbuffer, (intptr_t) ptr - logbuffer->ptr_base);
827
828         g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
829 }
830
831 static void
832 emit_method_inner (LogBuffer *logbuffer, void *method)
833 {
834         if (!logbuffer->method_base) {
835                 logbuffer->method_base = (intptr_t) method;
836                 logbuffer->last_method = (intptr_t) method;
837         }
838
839         encode_sleb128 ((intptr_t) ((char *) method - (char *) logbuffer->last_method), logbuffer->cursor, &logbuffer->cursor);
840         logbuffer->last_method = (intptr_t) method;
841
842         g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
843 }
844
845 // The reader lock must be held.
846 static void
847 register_method_local (MonoMethod *method, MonoJitInfo *ji)
848 {
849         MonoProfilerThread *thread = get_thread ();
850
851         if (!mono_conc_hashtable_lookup (log_profiler.method_table, method)) {
852                 MethodInfo *info = (MethodInfo *) g_malloc (sizeof (MethodInfo));
853
854                 info->method = method;
855                 info->ji = ji;
856                 info->time = current_time ();
857
858                 GPtrArray *arr = thread->methods ? thread->methods : (thread->methods = g_ptr_array_new ());
859                 g_ptr_array_add (arr, info);
860         }
861 }
862
863 static void
864 emit_method (LogBuffer *logbuffer, MonoMethod *method)
865 {
866         register_method_local (method, NULL);
867         emit_method_inner (logbuffer, method);
868 }
869
870 static void
871 emit_obj (LogBuffer *logbuffer, void *ptr)
872 {
873         if (!logbuffer->obj_base)
874                 logbuffer->obj_base = (uintptr_t) ptr >> 3;
875
876         emit_svalue (logbuffer, ((uintptr_t) ptr >> 3) - logbuffer->obj_base);
877
878         g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
879 }
880
881 static void
882 emit_string (LogBuffer *logbuffer, const char *str, size_t size)
883 {
884         size_t i = 0;
885         if (str) {
886                 for (; i < size; i++) {
887                         if (str[i] == '\0')
888                                 break;
889                         emit_byte (logbuffer, str [i]);
890                 }
891         }
892         emit_byte (logbuffer, '\0');
893 }
894
895 static void
896 emit_double (LogBuffer *logbuffer, double value)
897 {
898         int i;
899         unsigned char buffer[8];
900         memcpy (buffer, &value, 8);
901 #if G_BYTE_ORDER == G_BIG_ENDIAN
902         for (i = 7; i >= 0; i--)
903 #else
904         for (i = 0; i < 8; i++)
905 #endif
906                 emit_byte (logbuffer, buffer[i]);
907 }
908
909 static char*
910 write_int16 (char *buf, int32_t value)
911 {
912         int i;
913         for (i = 0; i < 2; ++i) {
914                 buf [i] = value;
915                 value >>= 8;
916         }
917         return buf + 2;
918 }
919
920 static char*
921 write_int32 (char *buf, int32_t value)
922 {
923         int i;
924         for (i = 0; i < 4; ++i) {
925                 buf [i] = value;
926                 value >>= 8;
927         }
928         return buf + 4;
929 }
930
931 static char*
932 write_int64 (char *buf, int64_t value)
933 {
934         int i;
935         for (i = 0; i < 8; ++i) {
936                 buf [i] = value;
937                 value >>= 8;
938         }
939         return buf + 8;
940 }
941
942 static char *
943 write_header_string (char *p, const char *str)
944 {
945         size_t len = strlen (str) + 1;
946
947         p = write_int32 (p, len);
948         strcpy (p, str);
949
950         return p + len;
951 }
952
953 static void
954 dump_header (void)
955 {
956         const char *args = log_profiler.args;
957         const char *arch = mono_config_get_cpu ();
958         const char *os = mono_config_get_os ();
959
960         char *hbuf = g_malloc (
961                 sizeof (gint32) /* header id */ +
962                 sizeof (gint8) /* major version */ +
963                 sizeof (gint8) /* minor version */ +
964                 sizeof (gint8) /* data version */ +
965                 sizeof (gint8) /* word size */ +
966                 sizeof (gint64) /* startup time */ +
967                 sizeof (gint32) /* timer overhead */ +
968                 sizeof (gint32) /* flags */ +
969                 sizeof (gint32) /* process id */ +
970                 sizeof (gint16) /* command port */ +
971                 sizeof (gint32) + strlen (args) + 1 /* arguments */ +
972                 sizeof (gint32) + strlen (arch) + 1 /* architecture */ +
973                 sizeof (gint32) + strlen (os) + 1 /* operating system */
974         );
975         char *p = hbuf;
976
977         p = write_int32 (p, LOG_HEADER_ID);
978         *p++ = LOG_VERSION_MAJOR;
979         *p++ = LOG_VERSION_MINOR;
980         *p++ = LOG_DATA_VERSION;
981         *p++ = sizeof (void *);
982         p = write_int64 (p, ((uint64_t) time (NULL)) * 1000);
983         p = write_int32 (p, log_profiler.timer_overhead);
984         p = write_int32 (p, 0); /* flags */
985         p = write_int32 (p, process_id ());
986         p = write_int16 (p, log_profiler.command_port);
987         p = write_header_string (p, args);
988         p = write_header_string (p, arch);
989         p = write_header_string (p, os);
990
991 #if defined (HAVE_SYS_ZLIB)
992         if (log_profiler.gzfile) {
993                 gzwrite (log_profiler.gzfile, hbuf, p - hbuf);
994         } else
995 #endif
996         {
997                 fwrite (hbuf, p - hbuf, 1, log_profiler.file);
998                 fflush (log_profiler.file);
999         }
1000
1001         g_free (hbuf);
1002 }
1003
1004 /*
1005  * Must be called with the reader lock held if thread is the current thread, or
1006  * the exclusive lock if thread is a different thread. However, if thread is
1007  * the current thread, and init_thread () was called with add_to_lls = FALSE,
1008  * then no locking is necessary.
1009  */
1010 static void
1011 send_buffer (MonoProfilerThread *thread)
1012 {
1013         WriterQueueEntry *entry = mono_lock_free_alloc (&log_profiler.writer_entry_allocator);
1014         entry->methods = thread->methods;
1015         entry->buffer = thread->buffer;
1016
1017         mono_lock_free_queue_node_init (&entry->node, FALSE);
1018
1019         mono_lock_free_queue_enqueue (&log_profiler.writer_queue, &entry->node);
1020         mono_os_sem_post (&log_profiler.writer_queue_sem);
1021 }
1022
1023 static void
1024 free_thread (gpointer p)
1025 {
1026         MonoProfilerThread *thread = p;
1027
1028         if (!thread->ended) {
1029                 /*
1030                  * The thread is being cleaned up by the main thread during
1031                  * shutdown. This typically happens for internal runtime
1032                  * threads. We need to synthesize a thread end event.
1033                  */
1034
1035                 InterlockedIncrement (&thread_ends_ctr);
1036
1037                 LogBuffer *buf = ensure_logbuf_unsafe (thread,
1038                         EVENT_SIZE /* event */ +
1039                         BYTE_SIZE /* type */ +
1040                         LEB128_SIZE /* tid */
1041                 );
1042
1043                 emit_event (buf, TYPE_END_UNLOAD | TYPE_METADATA);
1044                 emit_byte (buf, TYPE_THREAD);
1045                 emit_ptr (buf, (void *) thread->node.key);
1046         }
1047
1048         send_buffer (thread);
1049
1050         g_free (thread);
1051 }
1052
1053 static void
1054 remove_thread (MonoProfilerThread *thread)
1055 {
1056         MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
1057
1058         if (mono_lls_remove (&log_profiler.profiler_thread_list, hp, &thread->node))
1059                 mono_thread_hazardous_try_free (thread, free_thread);
1060
1061         clear_hazard_pointers (hp);
1062 }
1063
1064 static void
1065 dump_buffer (LogBuffer *buf)
1066 {
1067         char hbuf [128];
1068         char *p = hbuf;
1069
1070         if (buf->next)
1071                 dump_buffer (buf->next);
1072
1073         if (buf->cursor - buf->buf) {
1074                 p = write_int32 (p, BUF_ID);
1075                 p = write_int32 (p, buf->cursor - buf->buf);
1076                 p = write_int64 (p, buf->time_base);
1077                 p = write_int64 (p, buf->ptr_base);
1078                 p = write_int64 (p, buf->obj_base);
1079                 p = write_int64 (p, buf->thread_id);
1080                 p = write_int64 (p, buf->method_base);
1081
1082 #if defined (HAVE_SYS_ZLIB)
1083                 if (log_profiler.gzfile) {
1084                         gzwrite (log_profiler.gzfile, hbuf, p - hbuf);
1085                         gzwrite (log_profiler.gzfile, buf->buf, buf->cursor - buf->buf);
1086                 } else
1087 #endif
1088                 {
1089                         fwrite (hbuf, p - hbuf, 1, log_profiler.file);
1090                         fwrite (buf->buf, buf->cursor - buf->buf, 1, log_profiler.file);
1091                         fflush (log_profiler.file);
1092                 }
1093         }
1094
1095         free_buffer (buf, buf->size);
1096 }
1097
1098 static void
1099 dump_buffer_threadless (LogBuffer *buf)
1100 {
1101         for (LogBuffer *iter = buf; iter; iter = iter->next)
1102                 iter->thread_id = 0;
1103
1104         dump_buffer (buf);
1105 }
1106
1107 // Only valid if init_thread () was called with add_to_lls = FALSE.
1108 static void
1109 send_log_unsafe (gboolean if_needed)
1110 {
1111         MonoProfilerThread *thread = PROF_TLS_GET ();
1112
1113         if (!if_needed || (if_needed && thread->buffer->next)) {
1114                 if (!thread->attached)
1115                         for (LogBuffer *iter = thread->buffer; iter; iter = iter->next)
1116                                 iter->thread_id = 0;
1117
1118                 send_buffer (thread);
1119                 init_buffer_state (thread);
1120         }
1121 }
1122
1123 // Assumes that the exclusive lock is held.
1124 static void
1125 sync_point_flush (void)
1126 {
1127         g_assert (InterlockedRead (&log_profiler.buffer_lock_state) == PROF_TLS_GET ()->small_id << 16 && "Why don't we hold the exclusive lock?");
1128
1129         MONO_LLS_FOREACH_SAFE (&log_profiler.profiler_thread_list, MonoProfilerThread, thread) {
1130                 g_assert (thread->attached && "Why is a thread in the LLS not attached?");
1131
1132                 send_buffer (thread);
1133                 init_buffer_state (thread);
1134         } MONO_LLS_FOREACH_SAFE_END
1135 }
1136
1137 // Assumes that the exclusive lock is held.
1138 static void
1139 sync_point_mark (MonoProfilerSyncPointType type)
1140 {
1141         g_assert (InterlockedRead (&log_profiler.buffer_lock_state) == PROF_TLS_GET ()->small_id << 16 && "Why don't we hold the exclusive lock?");
1142
1143         ENTER_LOG (&sync_points_ctr, logbuffer,
1144                 EVENT_SIZE /* event */ +
1145                 BYTE_SIZE /* type */
1146         );
1147
1148         emit_event (logbuffer, TYPE_META | TYPE_SYNC_POINT);
1149         emit_byte (logbuffer, type);
1150
1151         EXIT_LOG_EXPLICIT (NO_SEND);
1152
1153         send_log_unsafe (FALSE);
1154 }
1155
1156 // Assumes that the exclusive lock is held.
1157 static void
1158 sync_point (MonoProfilerSyncPointType type)
1159 {
1160         sync_point_flush ();
1161         sync_point_mark (type);
1162 }
1163
1164 static int
1165 gc_reference (MonoObject *obj, MonoClass *klass, uintptr_t size, uintptr_t num, MonoObject **refs, uintptr_t *offsets, void *data)
1166 {
1167         /* account for object alignment in the heap */
1168         size += 7;
1169         size &= ~7;
1170
1171         ENTER_LOG (&heap_objects_ctr, logbuffer,
1172                 EVENT_SIZE /* event */ +
1173                 LEB128_SIZE /* obj */ +
1174                 LEB128_SIZE /* klass */ +
1175                 LEB128_SIZE /* size */ +
1176                 LEB128_SIZE /* num */ +
1177                 num * (
1178                         LEB128_SIZE /* offset */ +
1179                         LEB128_SIZE /* ref */
1180                 )
1181         );
1182
1183         emit_event (logbuffer, TYPE_HEAP_OBJECT | TYPE_HEAP);
1184         emit_obj (logbuffer, obj);
1185         emit_ptr (logbuffer, klass);
1186         emit_value (logbuffer, size);
1187         emit_value (logbuffer, num);
1188
1189         uintptr_t last_offset = 0;
1190
1191         for (int i = 0; i < num; ++i) {
1192                 emit_value (logbuffer, offsets [i] - last_offset);
1193                 last_offset = offsets [i];
1194                 emit_obj (logbuffer, refs [i]);
1195         }
1196
1197         EXIT_LOG;
1198
1199         return 0;
1200 }
1201
1202 static void
1203 gc_roots (MonoProfiler *prof, MonoObject *const *objects, const MonoProfilerGCRootType *root_types, const uintptr_t *extra_info, uint64_t num)
1204 {
1205         ENTER_LOG (&heap_roots_ctr, logbuffer,
1206                 EVENT_SIZE /* event */ +
1207                 LEB128_SIZE /* num */ +
1208                 LEB128_SIZE /* collections */ +
1209                 num * (
1210                         LEB128_SIZE /* object */ +
1211                         LEB128_SIZE /* root type */ +
1212                         LEB128_SIZE /* extra info */
1213                 )
1214         );
1215
1216         emit_event (logbuffer, TYPE_HEAP_ROOT | TYPE_HEAP);
1217         emit_value (logbuffer, num);
1218         emit_value (logbuffer, mono_gc_collection_count (mono_gc_max_generation ()));
1219
1220         for (int i = 0; i < num; ++i) {
1221                 emit_obj (logbuffer, objects [i]);
1222                 emit_value (logbuffer, root_types [i]);
1223                 emit_value (logbuffer, extra_info [i]);
1224         }
1225
1226         EXIT_LOG;
1227 }
1228
1229
1230 static void
1231 trigger_on_demand_heapshot (void)
1232 {
1233         if (InterlockedRead (&log_profiler.heapshot_requested))
1234                 mono_gc_collect (mono_gc_max_generation ());
1235 }
1236
1237 #define ALL_GC_EVENTS_MASK (PROFLOG_GC_EVENTS | PROFLOG_GC_MOVE_EVENTS | PROFLOG_GC_ROOT_EVENTS)
1238
1239 static void
1240 gc_event (MonoProfiler *profiler, MonoProfilerGCEvent ev, uint32_t generation)
1241 {
1242         if (ENABLED (PROFLOG_GC_EVENTS)) {
1243                 ENTER_LOG (&gc_events_ctr, logbuffer,
1244                         EVENT_SIZE /* event */ +
1245                         BYTE_SIZE /* gc event */ +
1246                         BYTE_SIZE /* generation */
1247                 );
1248
1249                 emit_event (logbuffer, TYPE_GC_EVENT | TYPE_GC);
1250                 emit_byte (logbuffer, ev);
1251                 emit_byte (logbuffer, generation);
1252
1253                 EXIT_LOG;
1254         }
1255
1256         switch (ev) {
1257         case MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED:
1258                 switch (log_config.hs_mode) {
1259                 case MONO_PROFILER_HEAPSHOT_NONE:
1260                         log_profiler.do_heap_walk = FALSE;
1261                         break;
1262                 case MONO_PROFILER_HEAPSHOT_MAJOR:
1263                         log_profiler.do_heap_walk = generation == mono_gc_max_generation ();
1264                         break;
1265                 case MONO_PROFILER_HEAPSHOT_ON_DEMAND:
1266                         log_profiler.do_heap_walk = InterlockedRead (&log_profiler.heapshot_requested);
1267                         break;
1268                 case MONO_PROFILER_HEAPSHOT_X_GC:
1269                         log_profiler.do_heap_walk = !(log_profiler.gc_count % log_config.hs_freq_gc);
1270                         break;
1271                 case MONO_PROFILER_HEAPSHOT_X_MS:
1272                         log_profiler.do_heap_walk = (current_time () - log_profiler.last_hs_time) / 1000 * 1000 >= log_config.hs_freq_ms;
1273                         break;
1274                 default:
1275                         g_assert_not_reached ();
1276                 }
1277
1278                 /*
1279                  * heapshot_requested is set either because on-demand heapshot is
1280                  * enabled and a heapshot was triggered, or because we're doing a
1281                  * shutdown heapshot. In the latter case, we won't check it in the
1282                  * switch above, so check it here and override any decision we made
1283                  * above.
1284                  */
1285                 if (InterlockedRead (&log_profiler.heapshot_requested))
1286                         log_profiler.do_heap_walk = TRUE;
1287
1288                 if (ENABLED (PROFLOG_GC_ROOT_EVENTS) && log_profiler.do_heap_walk)
1289                         mono_profiler_set_gc_roots_callback (log_profiler.handle, gc_roots);
1290
1291                 /*
1292                  * Ensure that no thread can be in the middle of writing to
1293                  * a buffer when the world stops...
1294                  */
1295                 buffer_lock_excl ();
1296
1297                 break;
1298         case MONO_GC_EVENT_POST_STOP_WORLD:
1299                 /*
1300                  * ... So that we now have a consistent view of all buffers.
1301                  * This allows us to flush them. We need to do this because
1302                  * they may contain object allocation events that need to be
1303                  * committed to the log file before any object move events
1304                  * that will be produced during this GC.
1305                  */
1306                 if (ENABLED (ALL_GC_EVENTS_MASK))
1307                         sync_point (SYNC_POINT_WORLD_STOP);
1308
1309                 // Surround heapshots with HEAP_START/HEAP_END events.
1310                 if (log_profiler.do_heap_walk) {
1311                         ENTER_LOG (&heap_starts_ctr, logbuffer,
1312                                 EVENT_SIZE /* event */
1313                         );
1314
1315                         emit_event (logbuffer, TYPE_HEAP_START | TYPE_HEAP);
1316
1317                         EXIT_LOG;
1318                 }
1319
1320                 break;
1321         case MONO_GC_EVENT_START:
1322                 if (generation == mono_gc_max_generation ())
1323                         log_profiler.gc_count++;
1324
1325                 break;
1326         case MONO_GC_EVENT_PRE_START_WORLD:
1327                 mono_profiler_set_gc_roots_callback (log_profiler.handle, NULL);
1328
1329                 if (log_profiler.do_heap_walk) {
1330                         mono_gc_walk_heap (0, gc_reference, NULL);
1331
1332                         ENTER_LOG (&heap_ends_ctr, logbuffer,
1333                                 EVENT_SIZE /* event */
1334                         );
1335
1336                         emit_event (logbuffer, TYPE_HEAP_END | TYPE_HEAP);
1337
1338                         EXIT_LOG;
1339
1340                         log_profiler.do_heap_walk = FALSE;
1341                         log_profiler.last_hs_time = current_time ();
1342
1343                         InterlockedWrite (&log_profiler.heapshot_requested, 0);
1344                 }
1345
1346                 /*
1347                  * Similarly, we must now make sure that any object moves
1348                  * written to the GC thread's buffer are flushed. Otherwise,
1349                  * object allocation events for certain addresses could come
1350                  * after the move events that made those addresses available.
1351                  */
1352                 if (ENABLED (ALL_GC_EVENTS_MASK))
1353                         sync_point_mark (SYNC_POINT_WORLD_START);
1354
1355                 break;
1356         case MONO_GC_EVENT_POST_START_WORLD_UNLOCKED:
1357                 /*
1358                  * Finally, it is safe to allow other threads to write to
1359                  * their buffers again.
1360                  */
1361                 buffer_unlock_excl ();
1362
1363                 break;
1364         default:
1365                 break;
1366         }
1367 }
1368
1369 static void
1370 gc_resize (MonoProfiler *profiler, uintptr_t new_size)
1371 {
1372         ENTER_LOG (&gc_resizes_ctr, logbuffer,
1373                 EVENT_SIZE /* event */ +
1374                 LEB128_SIZE /* new size */
1375         );
1376
1377         emit_event (logbuffer, TYPE_GC_RESIZE | TYPE_GC);
1378         emit_value (logbuffer, new_size);
1379
1380         EXIT_LOG;
1381 }
1382
1383 typedef struct {
1384         int count;
1385         MonoMethod* methods [MAX_FRAMES];
1386         int32_t il_offsets [MAX_FRAMES];
1387         int32_t native_offsets [MAX_FRAMES];
1388 } FrameData;
1389
1390 static mono_bool
1391 walk_stack (MonoMethod *method, int32_t native_offset, int32_t il_offset, mono_bool managed, void* data)
1392 {
1393         FrameData *frame = (FrameData *)data;
1394         if (method && frame->count < log_config.num_frames) {
1395                 frame->il_offsets [frame->count] = il_offset;
1396                 frame->native_offsets [frame->count] = native_offset;
1397                 frame->methods [frame->count++] = method;
1398         }
1399         return frame->count == log_config.num_frames;
1400 }
1401
1402 /*
1403  * a note about stack walks: they can cause more profiler events to fire,
1404  * so we need to make sure they don't happen after we started emitting an
1405  * event, hence the collect_bt/emit_bt split.
1406  */
1407 static void
1408 collect_bt (FrameData *data)
1409 {
1410         data->count = 0;
1411         mono_stack_walk_no_il (walk_stack, data);
1412 }
1413
1414 static void
1415 emit_bt (LogBuffer *logbuffer, FrameData *data)
1416 {
1417         emit_value (logbuffer, data->count);
1418
1419         while (data->count)
1420                 emit_method (logbuffer, data->methods [--data->count]);
1421 }
1422
1423 static void
1424 gc_alloc (MonoProfiler *prof, MonoObject *obj)
1425 {
1426         int do_bt = (!log_config.enter_leave && InterlockedRead (&log_profiler.runtime_inited) && log_config.num_frames) ? TYPE_ALLOC_BT : 0;
1427         FrameData data;
1428         uintptr_t len = mono_object_get_size (obj);
1429         /* account for object alignment in the heap */
1430         len += 7;
1431         len &= ~7;
1432
1433         if (do_bt)
1434                 collect_bt (&data);
1435
1436         ENTER_LOG (&gc_allocs_ctr, logbuffer,
1437                 EVENT_SIZE /* event */ +
1438                 LEB128_SIZE /* klass */ +
1439                 LEB128_SIZE /* obj */ +
1440                 LEB128_SIZE /* size */ +
1441                 (do_bt ? (
1442                         LEB128_SIZE /* count */ +
1443                         data.count * (
1444                                 LEB128_SIZE /* method */
1445                         )
1446                 ) : 0)
1447         );
1448
1449         emit_event (logbuffer, do_bt | TYPE_ALLOC);
1450         emit_ptr (logbuffer, mono_object_get_class (obj));
1451         emit_obj (logbuffer, obj);
1452         emit_value (logbuffer, len);
1453
1454         if (do_bt)
1455                 emit_bt (logbuffer, &data);
1456
1457         EXIT_LOG;
1458 }
1459
1460 static void
1461 gc_moves (MonoProfiler *prof, MonoObject *const *objects, uint64_t num)
1462 {
1463         ENTER_LOG (&gc_moves_ctr, logbuffer,
1464                 EVENT_SIZE /* event */ +
1465                 LEB128_SIZE /* num */ +
1466                 num * (
1467                         LEB128_SIZE /* object */
1468                 )
1469         );
1470
1471         emit_event (logbuffer, TYPE_GC_MOVE | TYPE_GC);
1472         emit_value (logbuffer, num);
1473
1474         for (int i = 0; i < num; ++i)
1475                 emit_obj (logbuffer, objects [i]);
1476
1477         EXIT_LOG;
1478 }
1479
1480 static void
1481 gc_handle (MonoProfiler *prof, int op, MonoGCHandleType type, uint32_t handle, MonoObject *obj)
1482 {
1483         int do_bt = !log_config.enter_leave && InterlockedRead (&log_profiler.runtime_inited) && log_config.num_frames;
1484         FrameData data;
1485
1486         if (do_bt)
1487                 collect_bt (&data);
1488
1489         gint32 *ctr = op == MONO_PROFILER_GC_HANDLE_CREATED ? &gc_handle_creations_ctr : &gc_handle_deletions_ctr;
1490
1491         ENTER_LOG (ctr, logbuffer,
1492                 EVENT_SIZE /* event */ +
1493                 LEB128_SIZE /* type */ +
1494                 LEB128_SIZE /* handle */ +
1495                 (op == MONO_PROFILER_GC_HANDLE_CREATED ? (
1496                         LEB128_SIZE /* obj */
1497                 ) : 0) +
1498                 (do_bt ? (
1499                         LEB128_SIZE /* count */ +
1500                         data.count * (
1501                                 LEB128_SIZE /* method */
1502                         )
1503                 ) : 0)
1504         );
1505
1506         if (op == MONO_PROFILER_GC_HANDLE_CREATED)
1507                 emit_event (logbuffer, (do_bt ? TYPE_GC_HANDLE_CREATED_BT : TYPE_GC_HANDLE_CREATED) | TYPE_GC);
1508         else if (op == MONO_PROFILER_GC_HANDLE_DESTROYED)
1509                 emit_event (logbuffer, (do_bt ? TYPE_GC_HANDLE_DESTROYED_BT : TYPE_GC_HANDLE_DESTROYED) | TYPE_GC);
1510         else
1511                 g_assert_not_reached ();
1512
1513         emit_value (logbuffer, type);
1514         emit_value (logbuffer, handle);
1515
1516         if (op == MONO_PROFILER_GC_HANDLE_CREATED)
1517                 emit_obj (logbuffer, obj);
1518
1519         if (do_bt)
1520                 emit_bt (logbuffer, &data);
1521
1522         EXIT_LOG;
1523 }
1524
1525 static void
1526 gc_handle_created (MonoProfiler *prof, uint32_t handle, MonoGCHandleType type, MonoObject *obj)
1527 {
1528         gc_handle (prof, MONO_PROFILER_GC_HANDLE_CREATED, type, handle, obj);
1529 }
1530
1531 static void
1532 gc_handle_deleted (MonoProfiler *prof, uint32_t handle, MonoGCHandleType type)
1533 {
1534         gc_handle (prof, MONO_PROFILER_GC_HANDLE_DESTROYED, type, handle, NULL);
1535 }
1536
1537 static void
1538 finalize_begin (MonoProfiler *prof)
1539 {
1540         ENTER_LOG (&finalize_begins_ctr, buf,
1541                 EVENT_SIZE /* event */
1542         );
1543
1544         emit_event (buf, TYPE_GC_FINALIZE_START | TYPE_GC);
1545
1546         EXIT_LOG;
1547 }
1548
1549 static void
1550 finalize_end (MonoProfiler *prof)
1551 {
1552         trigger_on_demand_heapshot ();
1553         if (ENABLED (PROFLOG_GC_FINALIZATION_EVENTS)) {
1554                 ENTER_LOG (&finalize_ends_ctr, buf,
1555                         EVENT_SIZE /* event */
1556                 );
1557
1558                 emit_event (buf, TYPE_GC_FINALIZE_END | TYPE_GC);
1559
1560                 EXIT_LOG;
1561         }
1562 }
1563
1564 static void
1565 finalize_object_begin (MonoProfiler *prof, MonoObject *obj)
1566 {
1567         ENTER_LOG (&finalize_object_begins_ctr, buf,
1568                 EVENT_SIZE /* event */ +
1569                 LEB128_SIZE /* obj */
1570         );
1571
1572         emit_event (buf, TYPE_GC_FINALIZE_OBJECT_START | TYPE_GC);
1573         emit_obj (buf, obj);
1574
1575         EXIT_LOG;
1576 }
1577
1578 static void
1579 finalize_object_end (MonoProfiler *prof, MonoObject *obj)
1580 {
1581         ENTER_LOG (&finalize_object_ends_ctr, buf,
1582                 EVENT_SIZE /* event */ +
1583                 LEB128_SIZE /* obj */
1584         );
1585
1586         emit_event (buf, TYPE_GC_FINALIZE_OBJECT_END | TYPE_GC);
1587         emit_obj (buf, obj);
1588
1589         EXIT_LOG;
1590 }
1591
1592 static char*
1593 push_nesting (char *p, MonoClass *klass)
1594 {
1595         MonoClass *nesting;
1596         const char *name;
1597         const char *nspace;
1598         nesting = mono_class_get_nesting_type (klass);
1599         if (nesting) {
1600                 p = push_nesting (p, nesting);
1601                 *p++ = '/';
1602                 *p = 0;
1603         }
1604         name = mono_class_get_name (klass);
1605         nspace = mono_class_get_namespace (klass);
1606         if (*nspace) {
1607                 strcpy (p, nspace);
1608                 p += strlen (nspace);
1609                 *p++ = '.';
1610                 *p = 0;
1611         }
1612         strcpy (p, name);
1613         p += strlen (name);
1614         return p;
1615 }
1616
1617 static char*
1618 type_name (MonoClass *klass)
1619 {
1620         char buf [1024];
1621         char *p;
1622         push_nesting (buf, klass);
1623         p = (char *) g_malloc (strlen (buf) + 1);
1624         strcpy (p, buf);
1625         return p;
1626 }
1627
1628 static void
1629 image_loaded (MonoProfiler *prof, MonoImage *image)
1630 {
1631         const char *name = mono_image_get_filename (image);
1632         int nlen = strlen (name) + 1;
1633
1634         ENTER_LOG (&image_loads_ctr, logbuffer,
1635                 EVENT_SIZE /* event */ +
1636                 BYTE_SIZE /* type */ +
1637                 LEB128_SIZE /* image */ +
1638                 nlen /* name */
1639         );
1640
1641         emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
1642         emit_byte (logbuffer, TYPE_IMAGE);
1643         emit_ptr (logbuffer, image);
1644         memcpy (logbuffer->cursor, name, nlen);
1645         logbuffer->cursor += nlen;
1646
1647         EXIT_LOG;
1648 }
1649
1650 static void
1651 image_unloaded (MonoProfiler *prof, MonoImage *image)
1652 {
1653         const char *name = mono_image_get_filename (image);
1654         int nlen = strlen (name) + 1;
1655
1656         ENTER_LOG (&image_unloads_ctr, logbuffer,
1657                 EVENT_SIZE /* event */ +
1658                 BYTE_SIZE /* type */ +
1659                 LEB128_SIZE /* image */ +
1660                 nlen /* name */
1661         );
1662
1663         emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
1664         emit_byte (logbuffer, TYPE_IMAGE);
1665         emit_ptr (logbuffer, image);
1666         memcpy (logbuffer->cursor, name, nlen);
1667         logbuffer->cursor += nlen;
1668
1669         EXIT_LOG;
1670 }
1671
1672 static void
1673 assembly_loaded (MonoProfiler *prof, MonoAssembly *assembly)
1674 {
1675         char *name = mono_stringify_assembly_name (mono_assembly_get_name (assembly));
1676         int nlen = strlen (name) + 1;
1677         MonoImage *image = mono_assembly_get_image (assembly);
1678
1679         ENTER_LOG (&assembly_loads_ctr, logbuffer,
1680                 EVENT_SIZE /* event */ +
1681                 BYTE_SIZE /* type */ +
1682                 LEB128_SIZE /* assembly */ +
1683                 LEB128_SIZE /* image */ +
1684                 nlen /* name */
1685         );
1686
1687         emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
1688         emit_byte (logbuffer, TYPE_ASSEMBLY);
1689         emit_ptr (logbuffer, assembly);
1690         emit_ptr (logbuffer, image);
1691         memcpy (logbuffer->cursor, name, nlen);
1692         logbuffer->cursor += nlen;
1693
1694         EXIT_LOG;
1695
1696         mono_free (name);
1697 }
1698
1699 static void
1700 assembly_unloaded (MonoProfiler *prof, MonoAssembly *assembly)
1701 {
1702         char *name = mono_stringify_assembly_name (mono_assembly_get_name (assembly));
1703         int nlen = strlen (name) + 1;
1704         MonoImage *image = mono_assembly_get_image (assembly);
1705
1706         ENTER_LOG (&assembly_unloads_ctr, logbuffer,
1707                 EVENT_SIZE /* event */ +
1708                 BYTE_SIZE /* type */ +
1709                 LEB128_SIZE /* assembly */ +
1710                 LEB128_SIZE /* image */ +
1711                 nlen /* name */
1712         );
1713
1714         emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
1715         emit_byte (logbuffer, TYPE_ASSEMBLY);
1716         emit_ptr (logbuffer, assembly);
1717         emit_ptr (logbuffer, image);
1718         memcpy (logbuffer->cursor, name, nlen);
1719         logbuffer->cursor += nlen;
1720
1721         EXIT_LOG;
1722
1723         mono_free (name);
1724 }
1725
1726 static void
1727 class_loaded (MonoProfiler *prof, MonoClass *klass)
1728 {
1729         char *name;
1730
1731         if (InterlockedRead (&log_profiler.runtime_inited))
1732                 name = mono_type_get_name (mono_class_get_type (klass));
1733         else
1734                 name = type_name (klass);
1735
1736         int nlen = strlen (name) + 1;
1737         MonoImage *image = mono_class_get_image (klass);
1738
1739         ENTER_LOG (&class_loads_ctr, logbuffer,
1740                 EVENT_SIZE /* event */ +
1741                 BYTE_SIZE /* type */ +
1742                 LEB128_SIZE /* klass */ +
1743                 LEB128_SIZE /* image */ +
1744                 nlen /* name */
1745         );
1746
1747         emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
1748         emit_byte (logbuffer, TYPE_CLASS);
1749         emit_ptr (logbuffer, klass);
1750         emit_ptr (logbuffer, image);
1751         memcpy (logbuffer->cursor, name, nlen);
1752         logbuffer->cursor += nlen;
1753
1754         EXIT_LOG;
1755
1756         if (InterlockedRead (&log_profiler.runtime_inited))
1757                 mono_free (name);
1758         else
1759                 g_free (name);
1760 }
1761
1762 static void
1763 method_enter (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *ctx)
1764 {
1765         if (get_thread ()->call_depth++ <= log_config.max_call_depth) {
1766                 ENTER_LOG (&method_entries_ctr, logbuffer,
1767                         EVENT_SIZE /* event */ +
1768                         LEB128_SIZE /* method */
1769                 );
1770
1771                 emit_event (logbuffer, TYPE_ENTER | TYPE_METHOD);
1772                 emit_method (logbuffer, method);
1773
1774                 EXIT_LOG;
1775         }
1776 }
1777
1778 static void
1779 method_leave (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *ctx)
1780 {
1781         if (--get_thread ()->call_depth <= log_config.max_call_depth) {
1782                 ENTER_LOG (&method_exits_ctr, logbuffer,
1783                         EVENT_SIZE /* event */ +
1784                         LEB128_SIZE /* method */
1785                 );
1786
1787                 emit_event (logbuffer, TYPE_LEAVE | TYPE_METHOD);
1788                 emit_method (logbuffer, method);
1789
1790                 EXIT_LOG;
1791         }
1792 }
1793
1794 static void
1795 tail_call (MonoProfiler *prof, MonoMethod *method, MonoMethod *target)
1796 {
1797         method_leave (prof, method, NULL);
1798 }
1799
1800 static void
1801 method_exc_leave (MonoProfiler *prof, MonoMethod *method, MonoObject *exc)
1802 {
1803         if (--get_thread ()->call_depth <= log_config.max_call_depth) {
1804                 ENTER_LOG (&method_exception_exits_ctr, logbuffer,
1805                         EVENT_SIZE /* event */ +
1806                         LEB128_SIZE /* method */
1807                 );
1808
1809                 emit_event (logbuffer, TYPE_EXC_LEAVE | TYPE_METHOD);
1810                 emit_method (logbuffer, method);
1811
1812                 EXIT_LOG;
1813         }
1814 }
1815
1816 static MonoProfilerCallInstrumentationFlags
1817 method_filter (MonoProfiler *prof, MonoMethod *method)
1818 {
1819         if (log_config.callspec.len > 0 &&
1820             !mono_callspec_eval (method, &log_config.callspec))
1821                 return MONO_PROFILER_CALL_INSTRUMENTATION_NONE;
1822
1823         return MONO_PROFILER_CALL_INSTRUMENTATION_ENTER |
1824                MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE |
1825                MONO_PROFILER_CALL_INSTRUMENTATION_TAIL_CALL |
1826                MONO_PROFILER_CALL_INSTRUMENTATION_EXCEPTION_LEAVE;
1827 }
1828
1829 static void
1830 method_jitted (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *ji)
1831 {
1832         buffer_lock ();
1833
1834         register_method_local (method, ji);
1835
1836         buffer_unlock ();
1837 }
1838
1839 static void
1840 code_buffer_new (MonoProfiler *prof, const mono_byte *buffer, uint64_t size, MonoProfilerCodeBufferType type, const void *data)
1841 {
1842         const char *name;
1843         int nlen;
1844
1845         if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE) {
1846                 name = (const char *) data;
1847                 nlen = strlen (name) + 1;
1848         } else {
1849                 name = NULL;
1850                 nlen = 0;
1851         }
1852
1853         ENTER_LOG (&code_buffers_ctr, logbuffer,
1854                 EVENT_SIZE /* event */ +
1855                 BYTE_SIZE /* type */ +
1856                 LEB128_SIZE /* buffer */ +
1857                 LEB128_SIZE /* size */ +
1858                 (name ? (
1859                         nlen /* name */
1860                 ) : 0)
1861         );
1862
1863         emit_event (logbuffer, TYPE_JITHELPER | TYPE_RUNTIME);
1864         emit_byte (logbuffer, type);
1865         emit_ptr (logbuffer, buffer);
1866         emit_value (logbuffer, size);
1867
1868         if (name) {
1869                 memcpy (logbuffer->cursor, name, nlen);
1870                 logbuffer->cursor += nlen;
1871         }
1872
1873         EXIT_LOG;
1874 }
1875
1876 static void
1877 throw_exc (MonoProfiler *prof, MonoObject *object)
1878 {
1879         int do_bt = (!log_config.enter_leave && InterlockedRead (&log_profiler.runtime_inited) && log_config.num_frames) ? TYPE_THROW_BT : 0;
1880         FrameData data;
1881
1882         if (do_bt)
1883                 collect_bt (&data);
1884
1885         ENTER_LOG (&exception_throws_ctr, logbuffer,
1886                 EVENT_SIZE /* event */ +
1887                 LEB128_SIZE /* object */ +
1888                 (do_bt ? (
1889                         LEB128_SIZE /* count */ +
1890                         data.count * (
1891                                 LEB128_SIZE /* method */
1892                         )
1893                 ) : 0)
1894         );
1895
1896         emit_event (logbuffer, do_bt | TYPE_EXCEPTION);
1897         emit_obj (logbuffer, object);
1898
1899         if (do_bt)
1900                 emit_bt (logbuffer, &data);
1901
1902         EXIT_LOG;
1903 }
1904
1905 static void
1906 clause_exc (MonoProfiler *prof, MonoMethod *method, uint32_t clause_num, MonoExceptionEnum clause_type, MonoObject *exc)
1907 {
1908         ENTER_LOG (&exception_clauses_ctr, logbuffer,
1909                 EVENT_SIZE /* event */ +
1910                 BYTE_SIZE /* clause type */ +
1911                 LEB128_SIZE /* clause num */ +
1912                 LEB128_SIZE /* method */ +
1913                 LEB128_SIZE /* exc */
1914         );
1915
1916         emit_event (logbuffer, TYPE_EXCEPTION | TYPE_CLAUSE);
1917         emit_byte (logbuffer, clause_type);
1918         emit_value (logbuffer, clause_num);
1919         emit_method (logbuffer, method);
1920         emit_obj (logbuffer, exc);
1921
1922         EXIT_LOG;
1923 }
1924
1925 static void
1926 monitor_event (MonoProfiler *profiler, MonoObject *object, MonoProfilerMonitorEvent ev)
1927 {
1928         int do_bt = (!log_config.enter_leave && InterlockedRead (&log_profiler.runtime_inited) && log_config.num_frames) ? TYPE_MONITOR_BT : 0;
1929         FrameData data;
1930
1931         if (do_bt)
1932                 collect_bt (&data);
1933
1934         ENTER_LOG (&monitor_events_ctr, logbuffer,
1935                 EVENT_SIZE /* event */ +
1936                 BYTE_SIZE /* ev */ +
1937                 LEB128_SIZE /* object */ +
1938                 (do_bt ? (
1939                         LEB128_SIZE /* count */ +
1940                         data.count * (
1941                                 LEB128_SIZE /* method */
1942                         )
1943                 ) : 0)
1944         );
1945
1946         emit_event (logbuffer, do_bt | TYPE_MONITOR);
1947         emit_byte (logbuffer, ev);
1948         emit_obj (logbuffer, object);
1949
1950         if (do_bt)
1951                 emit_bt (logbuffer, &data);
1952
1953         EXIT_LOG;
1954 }
1955
1956 static void
1957 monitor_contention (MonoProfiler *prof, MonoObject *object)
1958 {
1959         monitor_event (prof, object, MONO_PROFILER_MONITOR_CONTENTION);
1960 }
1961
1962 static void
1963 monitor_acquired (MonoProfiler *prof, MonoObject *object)
1964 {
1965         monitor_event (prof, object, MONO_PROFILER_MONITOR_DONE);
1966 }
1967
1968 static void
1969 monitor_failed (MonoProfiler *prof, MonoObject *object)
1970 {
1971         monitor_event (prof, object, MONO_PROFILER_MONITOR_FAIL);
1972 }
1973
1974 static void
1975 thread_start (MonoProfiler *prof, uintptr_t tid)
1976 {
1977         ENTER_LOG (&thread_starts_ctr, logbuffer,
1978                 EVENT_SIZE /* event */ +
1979                 BYTE_SIZE /* type */ +
1980                 LEB128_SIZE /* tid */
1981         );
1982
1983         emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
1984         emit_byte (logbuffer, TYPE_THREAD);
1985         emit_ptr (logbuffer, (void*) tid);
1986
1987         EXIT_LOG;
1988 }
1989
1990 static void
1991 thread_end (MonoProfiler *prof, uintptr_t tid)
1992 {
1993         ENTER_LOG (&thread_ends_ctr, logbuffer,
1994                 EVENT_SIZE /* event */ +
1995                 BYTE_SIZE /* type */ +
1996                 LEB128_SIZE /* tid */
1997         );
1998
1999         emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
2000         emit_byte (logbuffer, TYPE_THREAD);
2001         emit_ptr (logbuffer, (void*) tid);
2002
2003         EXIT_LOG_EXPLICIT (NO_SEND);
2004
2005         MonoProfilerThread *thread = get_thread ();
2006
2007         thread->ended = TRUE;
2008         remove_thread (thread);
2009
2010         PROF_TLS_SET (NULL);
2011 }
2012
2013 static void
2014 thread_name (MonoProfiler *prof, uintptr_t tid, const char *name)
2015 {
2016         int len = strlen (name) + 1;
2017
2018         ENTER_LOG (&thread_names_ctr, logbuffer,
2019                 EVENT_SIZE /* event */ +
2020                 BYTE_SIZE /* type */ +
2021                 LEB128_SIZE /* tid */ +
2022                 len /* name */
2023         );
2024
2025         emit_event (logbuffer, TYPE_METADATA);
2026         emit_byte (logbuffer, TYPE_THREAD);
2027         emit_ptr (logbuffer, (void*)tid);
2028         memcpy (logbuffer->cursor, name, len);
2029         logbuffer->cursor += len;
2030
2031         EXIT_LOG;
2032 }
2033
2034 static void
2035 domain_loaded (MonoProfiler *prof, MonoDomain *domain)
2036 {
2037         ENTER_LOG (&domain_loads_ctr, logbuffer,
2038                 EVENT_SIZE /* event */ +
2039                 BYTE_SIZE /* type */ +
2040                 LEB128_SIZE /* domain id */
2041         );
2042
2043         emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
2044         emit_byte (logbuffer, TYPE_DOMAIN);
2045         emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
2046
2047         EXIT_LOG;
2048 }
2049
2050 static void
2051 domain_unloaded (MonoProfiler *prof, MonoDomain *domain)
2052 {
2053         ENTER_LOG (&domain_unloads_ctr, logbuffer,
2054                 EVENT_SIZE /* event */ +
2055                 BYTE_SIZE /* type */ +
2056                 LEB128_SIZE /* domain id */
2057         );
2058
2059         emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
2060         emit_byte (logbuffer, TYPE_DOMAIN);
2061         emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
2062
2063         EXIT_LOG;
2064 }
2065
2066 static void
2067 domain_name (MonoProfiler *prof, MonoDomain *domain, const char *name)
2068 {
2069         int nlen = strlen (name) + 1;
2070
2071         ENTER_LOG (&domain_names_ctr, logbuffer,
2072                 EVENT_SIZE /* event */ +
2073                 BYTE_SIZE /* type */ +
2074                 LEB128_SIZE /* domain id */ +
2075                 nlen /* name */
2076         );
2077
2078         emit_event (logbuffer, TYPE_METADATA);
2079         emit_byte (logbuffer, TYPE_DOMAIN);
2080         emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
2081         memcpy (logbuffer->cursor, name, nlen);
2082         logbuffer->cursor += nlen;
2083
2084         EXIT_LOG;
2085 }
2086
2087 static void
2088 context_loaded (MonoProfiler *prof, MonoAppContext *context)
2089 {
2090         ENTER_LOG (&context_loads_ctr, logbuffer,
2091                 EVENT_SIZE /* event */ +
2092                 BYTE_SIZE /* type */ +
2093                 LEB128_SIZE /* context id */ +
2094                 LEB128_SIZE /* domain id */
2095         );
2096
2097         emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
2098         emit_byte (logbuffer, TYPE_CONTEXT);
2099         emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_id (context));
2100         emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_domain_id (context));
2101
2102         EXIT_LOG;
2103 }
2104
2105 static void
2106 context_unloaded (MonoProfiler *prof, MonoAppContext *context)
2107 {
2108         ENTER_LOG (&context_unloads_ctr, logbuffer,
2109                 EVENT_SIZE /* event */ +
2110                 BYTE_SIZE /* type */ +
2111                 LEB128_SIZE /* context id */ +
2112                 LEB128_SIZE /* domain id */
2113         );
2114
2115         emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
2116         emit_byte (logbuffer, TYPE_CONTEXT);
2117         emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_id (context));
2118         emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_domain_id (context));
2119
2120         EXIT_LOG;
2121 }
2122
2123 typedef struct {
2124         MonoMethod *method;
2125         MonoDomain *domain;
2126         void *base_address;
2127         int offset;
2128 } AsyncFrameInfo;
2129
2130 typedef struct {
2131         MonoLockFreeQueueNode node;
2132         uint64_t time;
2133         uintptr_t tid;
2134         const void *ip;
2135         int count;
2136         AsyncFrameInfo frames [MONO_ZERO_LEN_ARRAY];
2137 } SampleHit;
2138
2139 static mono_bool
2140 async_walk_stack (MonoMethod *method, MonoDomain *domain, void *base_address, int offset, void *data)
2141 {
2142         SampleHit *sample = (SampleHit *) data;
2143
2144         if (sample->count < log_config.num_frames) {
2145                 int i = sample->count;
2146
2147                 sample->frames [i].method = method;
2148                 sample->frames [i].domain = domain;
2149                 sample->frames [i].base_address = base_address;
2150                 sample->frames [i].offset = offset;
2151
2152                 sample->count++;
2153         }
2154
2155         return sample->count == log_config.num_frames;
2156 }
2157
2158 #define SAMPLE_SLOT_SIZE(FRAMES) (sizeof (SampleHit) + sizeof (AsyncFrameInfo) * (FRAMES - MONO_ZERO_LEN_ARRAY))
2159 #define SAMPLE_BLOCK_SIZE (mono_pagesize ())
2160
2161 static void
2162 enqueue_sample_hit (gpointer p)
2163 {
2164         SampleHit *sample = p;
2165
2166         mono_lock_free_queue_node_unpoison (&sample->node);
2167         mono_lock_free_queue_enqueue (&log_profiler.dumper_queue, &sample->node);
2168         mono_os_sem_post (&log_profiler.dumper_queue_sem);
2169 }
2170
2171 static void
2172 mono_sample_hit (MonoProfiler *profiler, const mono_byte *ip, const void *context)
2173 {
2174         /*
2175          * Please note: We rely on the runtime loading the profiler with
2176          * MONO_DL_EAGER (RTLD_NOW) so that references to runtime functions within
2177          * this function (and its siblings) are resolved when the profiler is
2178          * loaded. Otherwise, we would potentially invoke the dynamic linker when
2179          * invoking runtime functions, which is not async-signal-safe.
2180          */
2181
2182         if (InterlockedRead (&log_profiler.in_shutdown))
2183                 return;
2184
2185         SampleHit *sample = (SampleHit *) mono_lock_free_queue_dequeue (&profiler->sample_reuse_queue);
2186
2187         if (!sample) {
2188                 /*
2189                  * If we're out of reusable sample events and we're not allowed to
2190                  * allocate more, we have no choice but to drop the event.
2191                  */
2192                 if (InterlockedRead (&sample_allocations_ctr) >= log_config.max_allocated_sample_hits)
2193                         return;
2194
2195                 sample = mono_lock_free_alloc (&profiler->sample_allocator);
2196                 mono_lock_free_queue_node_init (&sample->node, TRUE);
2197
2198                 InterlockedIncrement (&sample_allocations_ctr);
2199         }
2200
2201         sample->count = 0;
2202         mono_stack_walk_async_safe (&async_walk_stack, (void *) context, sample);
2203
2204         sample->time = current_time ();
2205         sample->tid = thread_id ();
2206         sample->ip = ip;
2207
2208         mono_thread_hazardous_try_free (sample, enqueue_sample_hit);
2209 }
2210
2211 static uintptr_t *code_pages = 0;
2212 static int num_code_pages = 0;
2213 static int size_code_pages = 0;
2214 #define CPAGE_SHIFT (9)
2215 #define CPAGE_SIZE (1 << CPAGE_SHIFT)
2216 #define CPAGE_MASK (~(CPAGE_SIZE - 1))
2217 #define CPAGE_ADDR(p) ((p) & CPAGE_MASK)
2218
2219 static uintptr_t
2220 add_code_page (uintptr_t *hash, uintptr_t hsize, uintptr_t page)
2221 {
2222         uintptr_t i;
2223         uintptr_t start_pos;
2224         start_pos = (page >> CPAGE_SHIFT) % hsize;
2225         i = start_pos;
2226         do {
2227                 if (hash [i] && CPAGE_ADDR (hash [i]) == CPAGE_ADDR (page)) {
2228                         return 0;
2229                 } else if (!hash [i]) {
2230                         hash [i] = page;
2231                         return 1;
2232                 }
2233                 /* wrap around */
2234                 if (++i == hsize)
2235                         i = 0;
2236         } while (i != start_pos);
2237         g_assert_not_reached ();
2238         return 0;
2239 }
2240
2241 static void
2242 add_code_pointer (uintptr_t ip)
2243 {
2244         uintptr_t i;
2245         if (num_code_pages * 2 >= size_code_pages) {
2246                 uintptr_t *n;
2247                 uintptr_t old_size = size_code_pages;
2248                 size_code_pages *= 2;
2249                 if (size_code_pages == 0)
2250                         size_code_pages = 16;
2251                 n = (uintptr_t *) g_calloc (sizeof (uintptr_t) * size_code_pages, 1);
2252                 for (i = 0; i < old_size; ++i) {
2253                         if (code_pages [i])
2254                                 add_code_page (n, size_code_pages, code_pages [i]);
2255                 }
2256                 if (code_pages)
2257                         g_free (code_pages);
2258                 code_pages = n;
2259         }
2260         num_code_pages += add_code_page (code_pages, size_code_pages, ip & CPAGE_MASK);
2261 }
2262
2263 /* ELF code crashes on some systems. */
2264 //#if defined(HAVE_DL_ITERATE_PHDR) && defined(ELFMAG0)
2265 #if 0
2266 static void
2267 dump_ubin (const char *filename, uintptr_t load_addr, uint64_t offset, uintptr_t size)
2268 {
2269         int len = strlen (filename) + 1;
2270
2271         ENTER_LOG (&sample_ubins_ctr, logbuffer,
2272                 EVENT_SIZE /* event */ +
2273                 LEB128_SIZE /* load address */ +
2274                 LEB128_SIZE /* offset */ +
2275                 LEB128_SIZE /* size */ +
2276                 len /* file name */
2277         );
2278
2279         emit_event (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_UBIN);
2280         emit_ptr (logbuffer, load_addr);
2281         emit_uvalue (logbuffer, offset);
2282         emit_uvalue (logbuffer, size);
2283         memcpy (logbuffer->cursor, filename, len);
2284         logbuffer->cursor += len;
2285
2286         EXIT_LOG;
2287 }
2288 #endif
2289
2290 static void
2291 dump_usym (const char *name, uintptr_t value, uintptr_t size)
2292 {
2293         int len = strlen (name) + 1;
2294
2295         ENTER_LOG (&sample_usyms_ctr, logbuffer,
2296                 EVENT_SIZE /* event */ +
2297                 LEB128_SIZE /* value */ +
2298                 LEB128_SIZE /* size */ +
2299                 len /* name */
2300         );
2301
2302         emit_event (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_USYM);
2303         emit_ptr (logbuffer, (void*)value);
2304         emit_value (logbuffer, size);
2305         memcpy (logbuffer->cursor, name, len);
2306         logbuffer->cursor += len;
2307
2308         EXIT_LOG;
2309 }
2310
2311 /* ELF code crashes on some systems. */
2312 //#if defined(ELFMAG0)
2313 #if 0
2314
2315 #if SIZEOF_VOID_P == 4
2316 #define ELF_WSIZE 32
2317 #else
2318 #define ELF_WSIZE 64
2319 #endif
2320 #ifndef ElfW
2321 #define ElfW(type)      _ElfW (Elf, ELF_WSIZE, type)
2322 #define _ElfW(e,w,t)    _ElfW_1 (e, w, _##t)
2323 #define _ElfW_1(e,w,t)  e##w##t
2324 #endif
2325
2326 static void
2327 dump_elf_symbols (ElfW(Sym) *symbols, int num_symbols, const char *strtab, void *load_addr)
2328 {
2329         int i;
2330         for (i = 0; i < num_symbols; ++i) {
2331                 const char* sym;
2332                 sym =  strtab + symbols [i].st_name;
2333                 if (!symbols [i].st_name || !symbols [i].st_size || (symbols [i].st_info & 0xf) != STT_FUNC)
2334                         continue;
2335                 dump_usym (sym, (uintptr_t)load_addr + symbols [i].st_value, symbols [i].st_size);
2336         }
2337 }
2338
2339 static int
2340 read_elf_symbols (MonoProfiler *prof, const char *filename, void *load_addr)
2341 {
2342         int fd, i;
2343         void *data;
2344         struct stat statb;
2345         uint64_t file_size;
2346         ElfW(Ehdr) *header;
2347         ElfW(Shdr) *sheader;
2348         ElfW(Shdr) *shstrtabh;
2349         ElfW(Shdr) *symtabh = NULL;
2350         ElfW(Shdr) *strtabh = NULL;
2351         ElfW(Sym) *symbols = NULL;
2352         const char *strtab;
2353         int num_symbols;
2354
2355         fd = open (filename, O_RDONLY);
2356         if (fd < 0)
2357                 return 0;
2358         if (fstat (fd, &statb) != 0) {
2359                 close (fd);
2360                 return 0;
2361         }
2362         file_size = statb.st_size;
2363         data = mmap (NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
2364         close (fd);
2365         if (data == MAP_FAILED)
2366                 return 0;
2367         header = data;
2368         if (header->e_ident [EI_MAG0] != ELFMAG0 ||
2369                         header->e_ident [EI_MAG1] != ELFMAG1 ||
2370                         header->e_ident [EI_MAG2] != ELFMAG2 ||
2371                         header->e_ident [EI_MAG3] != ELFMAG3 ) {
2372                 munmap (data, file_size);
2373                 return 0;
2374         }
2375         sheader = (void*)((char*)data + header->e_shoff);
2376         shstrtabh = (void*)((char*)sheader + (header->e_shentsize * header->e_shstrndx));
2377         strtab = (const char*)data + shstrtabh->sh_offset;
2378         for (i = 0; i < header->e_shnum; ++i) {
2379                 if (sheader->sh_type == SHT_SYMTAB) {
2380                         symtabh = sheader;
2381                         strtabh = (void*)((char*)data + header->e_shoff + sheader->sh_link * header->e_shentsize);
2382                         break;
2383                 }
2384                 sheader = (void*)((char*)sheader + header->e_shentsize);
2385         }
2386         if (!symtabh || !strtabh) {
2387                 munmap (data, file_size);
2388                 return 0;
2389         }
2390         strtab = (const char*)data + strtabh->sh_offset;
2391         num_symbols = symtabh->sh_size / symtabh->sh_entsize;
2392         symbols = (void*)((char*)data + symtabh->sh_offset);
2393         dump_elf_symbols (symbols, num_symbols, strtab, load_addr);
2394         munmap (data, file_size);
2395         return 1;
2396 }
2397 #endif
2398
2399 /* ELF code crashes on some systems. */
2400 //#if defined(HAVE_DL_ITERATE_PHDR) && defined(ELFMAG0)
2401 #if 0
2402 static int
2403 elf_dl_callback (struct dl_phdr_info *info, size_t size, void *data)
2404 {
2405         char buf [256];
2406         const char *filename;
2407         BinaryObject *obj;
2408         char *a = (void*)info->dlpi_addr;
2409         int i, num_sym;
2410         ElfW(Dyn) *dyn = NULL;
2411         ElfW(Sym) *symtab = NULL;
2412         ElfW(Word) *hash_table = NULL;
2413         ElfW(Ehdr) *header = NULL;
2414         const char* strtab = NULL;
2415         for (obj = log_profiler.binary_objects; obj; obj = obj->next) {
2416                 if (obj->addr == a)
2417                         return 0;
2418         }
2419         filename = info->dlpi_name;
2420         if (!filename)
2421                 return 0;
2422         if (!info->dlpi_addr && !filename [0]) {
2423                 int l = readlink ("/proc/self/exe", buf, sizeof (buf) - 1);
2424                 if (l > 0) {
2425                         buf [l] = 0;
2426                         filename = buf;
2427                 }
2428         }
2429         obj = g_calloc (sizeof (BinaryObject), 1);
2430         obj->addr = (void*)info->dlpi_addr;
2431         obj->name = pstrdup (filename);
2432         obj->next = log_profiler.binary_objects;
2433         log_profiler.binary_objects = obj;
2434         a = NULL;
2435         for (i = 0; i < info->dlpi_phnum; ++i) {
2436                 if (info->dlpi_phdr[i].p_type == PT_LOAD && !header) {
2437                         header = (ElfW(Ehdr)*)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
2438                         if (header->e_ident [EI_MAG0] != ELFMAG0 ||
2439                                         header->e_ident [EI_MAG1] != ELFMAG1 ||
2440                                         header->e_ident [EI_MAG2] != ELFMAG2 ||
2441                                         header->e_ident [EI_MAG3] != ELFMAG3 ) {
2442                                 header = NULL;
2443                         }
2444                         dump_ubin (filename, info->dlpi_addr + info->dlpi_phdr[i].p_vaddr, info->dlpi_phdr[i].p_offset, info->dlpi_phdr[i].p_memsz);
2445                 } else if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) {
2446                         dyn = (ElfW(Dyn) *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
2447                 }
2448         }
2449         if (read_elf_symbols (filename, (void*)info->dlpi_addr))
2450                 return 0;
2451         if (!info->dlpi_name || !info->dlpi_name[0])
2452                 return 0;
2453         if (!dyn)
2454                 return 0;
2455         for (i = 0; dyn [i].d_tag != DT_NULL; ++i) {
2456                 if (dyn [i].d_tag == DT_SYMTAB) {
2457                         symtab = (ElfW(Sym) *)(a + dyn [i].d_un.d_ptr);
2458                 } else if (dyn [i].d_tag == DT_HASH) {
2459                         hash_table = (ElfW(Word) *)(a + dyn [i].d_un.d_ptr);
2460                 } else if (dyn [i].d_tag == DT_STRTAB) {
2461                         strtab = (const char*)(a + dyn [i].d_un.d_ptr);
2462                 }
2463         }
2464         if (!hash_table)
2465                 return 0;
2466         num_sym = hash_table [1];
2467         dump_elf_symbols (symtab, num_sym, strtab, (void*)info->dlpi_addr);
2468         return 0;
2469 }
2470
2471 static int
2472 load_binaries (void)
2473 {
2474         dl_iterate_phdr (elf_dl_callback, NULL);
2475         return 1;
2476 }
2477 #else
2478 static int
2479 load_binaries (void)
2480 {
2481         return 0;
2482 }
2483 #endif
2484
2485 static const char*
2486 symbol_for (uintptr_t code)
2487 {
2488 #ifdef HAVE_DLADDR
2489         void *ip = (void*)code;
2490         Dl_info di;
2491         if (dladdr (ip, &di)) {
2492                 if (di.dli_sname)
2493                         return di.dli_sname;
2494         } else {
2495         /*      char **names;
2496                 names = backtrace_symbols (&ip, 1);
2497                 if (names) {
2498                         const char* p = names [0];
2499                         g_free (names);
2500                         return p;
2501                 }
2502                 */
2503         }
2504 #endif
2505         return NULL;
2506 }
2507
2508 static void
2509 dump_unmanaged_coderefs (void)
2510 {
2511         int i;
2512         const char* last_symbol;
2513         uintptr_t addr, page_end;
2514
2515         if (load_binaries ())
2516                 return;
2517         for (i = 0; i < size_code_pages; ++i) {
2518                 const char* sym;
2519                 if (!code_pages [i] || code_pages [i] & 1)
2520                         continue;
2521                 last_symbol = NULL;
2522                 addr = CPAGE_ADDR (code_pages [i]);
2523                 page_end = addr + CPAGE_SIZE;
2524                 code_pages [i] |= 1;
2525                 /* we dump the symbols for the whole page */
2526                 for (; addr < page_end; addr += 16) {
2527                         sym = symbol_for (addr);
2528                         if (sym && sym == last_symbol)
2529                                 continue;
2530                         last_symbol = sym;
2531                         if (!sym)
2532                                 continue;
2533                         dump_usym (sym, addr, 0); /* let's not guess the size */
2534                 }
2535         }
2536 }
2537
2538 static void
2539 counters_add_agent (MonoCounter *counter)
2540 {
2541         if (InterlockedRead (&log_profiler.in_shutdown))
2542                 return;
2543
2544         MonoCounterAgent *agent, *item;
2545
2546         mono_os_mutex_lock (&log_profiler.counters_mutex);
2547
2548         for (agent = log_profiler.counters; agent; agent = agent->next) {
2549                 if (agent->counter == counter) {
2550                         agent->value_size = 0;
2551                         if (agent->value) {
2552                                 g_free (agent->value);
2553                                 agent->value = NULL;
2554                         }
2555                         goto done;
2556                 }
2557         }
2558
2559         agent = (MonoCounterAgent *) g_malloc (sizeof (MonoCounterAgent));
2560         agent->counter = counter;
2561         agent->value = NULL;
2562         agent->value_size = 0;
2563         agent->index = log_profiler.counters_index++;
2564         agent->emitted = FALSE;
2565         agent->next = NULL;
2566
2567         if (!log_profiler.counters) {
2568                 log_profiler.counters = agent;
2569         } else {
2570                 item = log_profiler.counters;
2571                 while (item->next)
2572                         item = item->next;
2573                 item->next = agent;
2574         }
2575
2576 done:
2577         mono_os_mutex_unlock (&log_profiler.counters_mutex);
2578 }
2579
2580 static mono_bool
2581 counters_init_foreach_callback (MonoCounter *counter, gpointer data)
2582 {
2583         counters_add_agent (counter);
2584         return TRUE;
2585 }
2586
2587 static void
2588 counters_init (void)
2589 {
2590         mono_os_mutex_init (&log_profiler.counters_mutex);
2591
2592         log_profiler.counters_index = 1;
2593
2594         mono_counters_on_register (&counters_add_agent);
2595         mono_counters_foreach (counters_init_foreach_callback, NULL);
2596 }
2597
2598 static void
2599 counters_emit (void)
2600 {
2601         MonoCounterAgent *agent;
2602         int len = 0;
2603         int size =
2604                 EVENT_SIZE /* event */ +
2605                 LEB128_SIZE /* len */
2606         ;
2607
2608         mono_os_mutex_lock (&log_profiler.counters_mutex);
2609
2610         for (agent = log_profiler.counters; agent; agent = agent->next) {
2611                 if (agent->emitted)
2612                         continue;
2613
2614                 size +=
2615                         LEB128_SIZE /* section */ +
2616                         strlen (mono_counter_get_name (agent->counter)) + 1 /* name */ +
2617                         BYTE_SIZE /* type */ +
2618                         BYTE_SIZE /* unit */ +
2619                         BYTE_SIZE /* variance */ +
2620                         LEB128_SIZE /* index */
2621                 ;
2622
2623                 len++;
2624         }
2625
2626         if (!len)
2627                 goto done;
2628
2629         ENTER_LOG (&counter_descriptors_ctr, logbuffer, size);
2630
2631         emit_event (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
2632         emit_value (logbuffer, len);
2633
2634         for (agent = log_profiler.counters; agent; agent = agent->next) {
2635                 const char *name;
2636
2637                 if (agent->emitted)
2638                         continue;
2639
2640                 name = mono_counter_get_name (agent->counter);
2641                 emit_value (logbuffer, mono_counter_get_section (agent->counter));
2642                 emit_string (logbuffer, name, strlen (name) + 1);
2643                 emit_byte (logbuffer, mono_counter_get_type (agent->counter));
2644                 emit_byte (logbuffer, mono_counter_get_unit (agent->counter));
2645                 emit_byte (logbuffer, mono_counter_get_variance (agent->counter));
2646                 emit_value (logbuffer, agent->index);
2647
2648                 agent->emitted = TRUE;
2649         }
2650
2651         EXIT_LOG;
2652
2653 done:
2654         mono_os_mutex_unlock (&log_profiler.counters_mutex);
2655 }
2656
2657 static void
2658 counters_sample (uint64_t timestamp)
2659 {
2660         MonoCounterAgent *agent;
2661         MonoCounter *counter;
2662         int type;
2663         int buffer_size;
2664         void *buffer;
2665         int size;
2666
2667         counters_emit ();
2668
2669         buffer_size = 8;
2670         buffer = g_calloc (1, buffer_size);
2671
2672         mono_os_mutex_lock (&log_profiler.counters_mutex);
2673
2674         size =
2675                 EVENT_SIZE /* event */
2676         ;
2677
2678         for (agent = log_profiler.counters; agent; agent = agent->next) {
2679                 /*
2680                  * FIXME: This calculation is incorrect for string counters since
2681                  * mono_counter_get_size () just returns 0 in that case. We should
2682                  * address this if we ever actually add any string counters to Mono.
2683                  */
2684
2685                 size +=
2686                         LEB128_SIZE /* index */ +
2687                         BYTE_SIZE /* type */ +
2688                         mono_counter_get_size (agent->counter) /* value */
2689                 ;
2690         }
2691
2692         size +=
2693                 LEB128_SIZE /* stop marker */
2694         ;
2695
2696         ENTER_LOG (&counter_samples_ctr, logbuffer, size);
2697
2698         emit_event_time (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE, timestamp);
2699
2700         for (agent = log_profiler.counters; agent; agent = agent->next) {
2701                 size_t size;
2702
2703                 counter = agent->counter;
2704
2705                 size = mono_counter_get_size (counter);
2706
2707                 if (size > buffer_size) {
2708                         buffer_size = size;
2709                         buffer = g_realloc (buffer, buffer_size);
2710                 }
2711
2712                 memset (buffer, 0, buffer_size);
2713
2714                 g_assert (mono_counters_sample (counter, buffer, size));
2715
2716                 type = mono_counter_get_type (counter);
2717
2718                 if (!agent->value) {
2719                         agent->value = g_calloc (1, size);
2720                         agent->value_size = size;
2721                 } else {
2722                         if (type == MONO_COUNTER_STRING) {
2723                                 if (strcmp (agent->value, buffer) == 0)
2724                                         continue;
2725                         } else {
2726                                 if (agent->value_size == size && memcmp (agent->value, buffer, size) == 0)
2727                                         continue;
2728                         }
2729                 }
2730
2731                 emit_uvalue (logbuffer, agent->index);
2732                 emit_byte (logbuffer, type);
2733                 switch (type) {
2734                 case MONO_COUNTER_INT:
2735 #if SIZEOF_VOID_P == 4
2736                 case MONO_COUNTER_WORD:
2737 #endif
2738                         emit_svalue (logbuffer, *(int*)buffer - *(int*)agent->value);
2739                         break;
2740                 case MONO_COUNTER_UINT:
2741                         emit_uvalue (logbuffer, *(guint*)buffer - *(guint*)agent->value);
2742                         break;
2743                 case MONO_COUNTER_TIME_INTERVAL:
2744                 case MONO_COUNTER_LONG:
2745 #if SIZEOF_VOID_P == 8
2746                 case MONO_COUNTER_WORD:
2747 #endif
2748                         emit_svalue (logbuffer, *(gint64*)buffer - *(gint64*)agent->value);
2749                         break;
2750                 case MONO_COUNTER_ULONG:
2751                         emit_uvalue (logbuffer, *(guint64*)buffer - *(guint64*)agent->value);
2752                         break;
2753                 case MONO_COUNTER_DOUBLE:
2754                         emit_double (logbuffer, *(double*)buffer);
2755                         break;
2756                 case MONO_COUNTER_STRING:
2757                         if (size == 0) {
2758                                 emit_byte (logbuffer, 0);
2759                         } else {
2760                                 emit_byte (logbuffer, 1);
2761                                 emit_string (logbuffer, (char*)buffer, size);
2762                         }
2763                         break;
2764                 default:
2765                         g_assert_not_reached ();
2766                 }
2767
2768                 if (type == MONO_COUNTER_STRING && size > agent->value_size) {
2769                         agent->value = g_realloc (agent->value, size);
2770                         agent->value_size = size;
2771                 }
2772
2773                 if (size > 0)
2774                         memcpy (agent->value, buffer, size);
2775         }
2776         g_free (buffer);
2777
2778         emit_value (logbuffer, 0);
2779
2780         EXIT_LOG;
2781
2782         mono_os_mutex_unlock (&log_profiler.counters_mutex);
2783 }
2784
2785 static void
2786 perfcounters_emit (void)
2787 {
2788         PerfCounterAgent *pcagent;
2789         int len = 0;
2790         int size =
2791                 EVENT_SIZE /* event */ +
2792                 LEB128_SIZE /* len */
2793         ;
2794
2795         for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
2796                 if (pcagent->emitted)
2797                         continue;
2798
2799                 size +=
2800                         LEB128_SIZE /* section */ +
2801                         strlen (pcagent->category_name) + 1 /* category name */ +
2802                         strlen (pcagent->name) + 1 /* name */ +
2803                         BYTE_SIZE /* type */ +
2804                         BYTE_SIZE /* unit */ +
2805                         BYTE_SIZE /* variance */ +
2806                         LEB128_SIZE /* index */
2807                 ;
2808
2809                 len++;
2810         }
2811
2812         if (!len)
2813                 return;
2814
2815         ENTER_LOG (&perfcounter_descriptors_ctr, logbuffer, size);
2816
2817         emit_event (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
2818         emit_value (logbuffer, len);
2819
2820         for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
2821                 if (pcagent->emitted)
2822                         continue;
2823
2824                 emit_value (logbuffer, MONO_COUNTER_PERFCOUNTERS);
2825                 emit_string (logbuffer, pcagent->category_name, strlen (pcagent->category_name) + 1);
2826                 emit_string (logbuffer, pcagent->name, strlen (pcagent->name) + 1);
2827                 emit_byte (logbuffer, MONO_COUNTER_LONG);
2828                 emit_byte (logbuffer, MONO_COUNTER_RAW);
2829                 emit_byte (logbuffer, MONO_COUNTER_VARIABLE);
2830                 emit_value (logbuffer, pcagent->index);
2831
2832                 pcagent->emitted = TRUE;
2833         }
2834
2835         EXIT_LOG;
2836 }
2837
2838 static gboolean
2839 perfcounters_foreach (char *category_name, char *name, unsigned char type, gint64 value, gpointer user_data)
2840 {
2841         PerfCounterAgent *pcagent;
2842
2843         for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
2844                 if (strcmp (pcagent->category_name, category_name) != 0 || strcmp (pcagent->name, name) != 0)
2845                         continue;
2846                 if (pcagent->value == value)
2847                         return TRUE;
2848
2849                 pcagent->value = value;
2850                 pcagent->updated = TRUE;
2851                 pcagent->deleted = FALSE;
2852                 return TRUE;
2853         }
2854
2855         pcagent = g_new0 (PerfCounterAgent, 1);
2856         pcagent->next = log_profiler.perfcounters;
2857         pcagent->index = log_profiler.counters_index++;
2858         pcagent->category_name = g_strdup (category_name);
2859         pcagent->name = g_strdup (name);
2860         pcagent->value = value;
2861         pcagent->emitted = FALSE;
2862         pcagent->updated = TRUE;
2863         pcagent->deleted = FALSE;
2864
2865         log_profiler.perfcounters = pcagent;
2866
2867         return TRUE;
2868 }
2869
2870 static void
2871 perfcounters_sample (uint64_t timestamp)
2872 {
2873         PerfCounterAgent *pcagent;
2874         int len = 0;
2875         int size;
2876
2877         mono_os_mutex_lock (&log_profiler.counters_mutex);
2878
2879         /* mark all perfcounters as deleted, foreach will unmark them as necessary */
2880         for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next)
2881                 pcagent->deleted = TRUE;
2882
2883         mono_perfcounter_foreach (perfcounters_foreach, NULL);
2884
2885         perfcounters_emit ();
2886
2887         size =
2888                 EVENT_SIZE /* event */
2889         ;
2890
2891         for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
2892                 if (pcagent->deleted || !pcagent->updated)
2893                         continue;
2894
2895                 size +=
2896                         LEB128_SIZE /* index */ +
2897                         BYTE_SIZE /* type */ +
2898                         LEB128_SIZE /* value */
2899                 ;
2900
2901                 len++;
2902         }
2903
2904         if (!len)
2905                 goto done;
2906
2907         size +=
2908                 LEB128_SIZE /* stop marker */
2909         ;
2910
2911         ENTER_LOG (&perfcounter_samples_ctr, logbuffer, size);
2912
2913         emit_event_time (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE, timestamp);
2914
2915         for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
2916                 if (pcagent->deleted || !pcagent->updated)
2917                         continue;
2918                 emit_uvalue (logbuffer, pcagent->index);
2919                 emit_byte (logbuffer, MONO_COUNTER_LONG);
2920                 emit_svalue (logbuffer, pcagent->value);
2921
2922                 pcagent->updated = FALSE;
2923         }
2924
2925         emit_value (logbuffer, 0);
2926
2927         EXIT_LOG;
2928
2929 done:
2930         mono_os_mutex_unlock (&log_profiler.counters_mutex);
2931 }
2932
2933 static void
2934 counters_and_perfcounters_sample (void)
2935 {
2936         uint64_t now = current_time ();
2937
2938         counters_sample (now);
2939         perfcounters_sample (now);
2940 }
2941
2942 typedef struct {
2943         MonoLockFreeQueueNode node;
2944         MonoMethod *method;
2945 } MethodNode;
2946
2947 typedef struct {
2948         int offset;
2949         int counter;
2950         char *filename;
2951         int line;
2952         int column;
2953 } CoverageEntry;
2954
2955 static void
2956 free_coverage_entry (gpointer data, gpointer userdata)
2957 {
2958         CoverageEntry *entry = (CoverageEntry *)data;
2959         g_free (entry->filename);
2960         g_free (entry);
2961 }
2962
2963 static void
2964 obtain_coverage_for_method (MonoProfiler *prof, const MonoProfilerCoverageData *entry)
2965 {
2966         int offset = entry->il_offset - log_profiler.coverage_previous_offset;
2967         CoverageEntry *e = g_new (CoverageEntry, 1);
2968
2969         log_profiler.coverage_previous_offset = entry->il_offset;
2970
2971         e->offset = offset;
2972         e->counter = entry->counter;
2973         e->filename = g_strdup(entry->file_name ? entry->file_name : "");
2974         e->line = entry->line;
2975         e->column = entry->column;
2976
2977         g_ptr_array_add (log_profiler.coverage_data, e);
2978 }
2979
2980 static char *
2981 parse_generic_type_names(char *name)
2982 {
2983         char *new_name, *ret;
2984         int within_generic_declaration = 0, generic_members = 1;
2985
2986         if (name == NULL || *name == '\0')
2987                 return g_strdup ("");
2988
2989         if (!(ret = new_name = (char *) g_calloc (strlen (name) * 4 + 1, sizeof (char))))
2990                 return NULL;
2991
2992         do {
2993                 switch (*name) {
2994                         case '<':
2995                                 within_generic_declaration = 1;
2996                                 break;
2997
2998                         case '>':
2999                                 within_generic_declaration = 0;
3000
3001                                 if (*(name - 1) != '<') {
3002                                         *new_name++ = '`';
3003                                         *new_name++ = '0' + generic_members;
3004                                 } else {
3005                                         memcpy (new_name, "&lt;&gt;", 8);
3006                                         new_name += 8;
3007                                 }
3008
3009                                 generic_members = 0;
3010                                 break;
3011
3012                         case ',':
3013                                 generic_members++;
3014                                 break;
3015
3016                         default:
3017                                 if (!within_generic_declaration)
3018                                         *new_name++ = *name;
3019
3020                                 break;
3021                 }
3022         } while (*name++);
3023
3024         return ret;
3025 }
3026
3027 static void
3028 build_method_buffer (gpointer key, gpointer value, gpointer userdata)
3029 {
3030         MonoMethod *method = (MonoMethod *)value;
3031         MonoClass *klass;
3032         MonoImage *image;
3033         char *class_name;
3034         const char *image_name, *method_name, *sig, *first_filename;
3035         guint i;
3036
3037         log_profiler.coverage_previous_offset = 0;
3038         log_profiler.coverage_data = g_ptr_array_new ();
3039
3040         mono_profiler_get_coverage_data (log_profiler.handle, method, obtain_coverage_for_method);
3041
3042         klass = mono_method_get_class (method);
3043         image = mono_class_get_image (klass);
3044         image_name = mono_image_get_name (image);
3045
3046         sig = mono_signature_get_desc (mono_method_signature (method), TRUE);
3047         class_name = parse_generic_type_names (mono_type_get_name (mono_class_get_type (klass)));
3048         method_name = mono_method_get_name (method);
3049
3050         if (log_profiler.coverage_data->len != 0) {
3051                 CoverageEntry *entry = (CoverageEntry *)log_profiler.coverage_data->pdata[0];
3052                 first_filename = entry->filename ? entry->filename : "";
3053         } else
3054                 first_filename = "";
3055
3056         image_name = image_name ? image_name : "";
3057         sig = sig ? sig : "";
3058         method_name = method_name ? method_name : "";
3059
3060         ENTER_LOG (&coverage_methods_ctr, logbuffer,
3061                 EVENT_SIZE /* event */ +
3062                 strlen (image_name) + 1 /* image name */ +
3063                 strlen (class_name) + 1 /* class name */ +
3064                 strlen (method_name) + 1 /* method name */ +
3065                 strlen (sig) + 1 /* signature */ +
3066                 strlen (first_filename) + 1 /* first file name */ +
3067                 LEB128_SIZE /* token */ +
3068                 LEB128_SIZE /* method id */ +
3069                 LEB128_SIZE /* entries */
3070         );
3071
3072         emit_event (logbuffer, TYPE_COVERAGE_METHOD | TYPE_COVERAGE);
3073         emit_string (logbuffer, image_name, strlen (image_name) + 1);
3074         emit_string (logbuffer, class_name, strlen (class_name) + 1);
3075         emit_string (logbuffer, method_name, strlen (method_name) + 1);
3076         emit_string (logbuffer, sig, strlen (sig) + 1);
3077         emit_string (logbuffer, first_filename, strlen (first_filename) + 1);
3078
3079         emit_uvalue (logbuffer, mono_method_get_token (method));
3080         emit_uvalue (logbuffer, log_profiler.coverage_method_id);
3081         emit_value (logbuffer, log_profiler.coverage_data->len);
3082
3083         EXIT_LOG;
3084
3085         for (i = 0; i < log_profiler.coverage_data->len; i++) {
3086                 CoverageEntry *entry = (CoverageEntry *)log_profiler.coverage_data->pdata[i];
3087
3088                 ENTER_LOG (&coverage_statements_ctr, logbuffer,
3089                         EVENT_SIZE /* event */ +
3090                         LEB128_SIZE /* method id */ +
3091                         LEB128_SIZE /* offset */ +
3092                         LEB128_SIZE /* counter */ +
3093                         LEB128_SIZE /* line */ +
3094                         LEB128_SIZE /* column */
3095                 );
3096
3097                 emit_event (logbuffer, TYPE_COVERAGE_STATEMENT | TYPE_COVERAGE);
3098                 emit_uvalue (logbuffer, log_profiler.coverage_method_id);
3099                 emit_uvalue (logbuffer, entry->offset);
3100                 emit_uvalue (logbuffer, entry->counter);
3101                 emit_uvalue (logbuffer, entry->line);
3102                 emit_uvalue (logbuffer, entry->column);
3103
3104                 EXIT_LOG;
3105         }
3106
3107         log_profiler.coverage_method_id++;
3108
3109         g_free (class_name);
3110
3111         g_ptr_array_foreach (log_profiler.coverage_data, free_coverage_entry, NULL);
3112         g_ptr_array_free (log_profiler.coverage_data, TRUE);
3113 }
3114
3115 /* This empties the queue */
3116 static guint
3117 count_queue (MonoLockFreeQueue *queue)
3118 {
3119         MonoLockFreeQueueNode *node;
3120         guint count = 0;
3121
3122         while ((node = mono_lock_free_queue_dequeue (queue))) {
3123                 count++;
3124                 mono_thread_hazardous_try_free (node, g_free);
3125         }
3126
3127         return count;
3128 }
3129
3130 static void
3131 build_class_buffer (gpointer key, gpointer value, gpointer userdata)
3132 {
3133         MonoClass *klass = (MonoClass *)key;
3134         MonoLockFreeQueue *class_methods = (MonoLockFreeQueue *)value;
3135         MonoImage *image;
3136         char *class_name;
3137         const char *assembly_name;
3138         int number_of_methods, partially_covered;
3139         guint fully_covered;
3140
3141         image = mono_class_get_image (klass);
3142         assembly_name = mono_image_get_name (image);
3143         class_name = mono_type_get_name (mono_class_get_type (klass));
3144
3145         assembly_name = assembly_name ? assembly_name : "";
3146         number_of_methods = mono_class_num_methods (klass);
3147         fully_covered = count_queue (class_methods);
3148         /* We don't handle partial covered yet */
3149         partially_covered = 0;
3150
3151         ENTER_LOG (&coverage_classes_ctr, logbuffer,
3152                 EVENT_SIZE /* event */ +
3153                 strlen (assembly_name) + 1 /* assembly name */ +
3154                 strlen (class_name) + 1 /* class name */ +
3155                 LEB128_SIZE /* no. methods */ +
3156                 LEB128_SIZE /* fully covered */ +
3157                 LEB128_SIZE /* partially covered */
3158         );
3159
3160         emit_event (logbuffer, TYPE_COVERAGE_CLASS | TYPE_COVERAGE);
3161         emit_string (logbuffer, assembly_name, strlen (assembly_name) + 1);
3162         emit_string (logbuffer, class_name, strlen (class_name) + 1);
3163         emit_uvalue (logbuffer, number_of_methods);
3164         emit_uvalue (logbuffer, fully_covered);
3165         emit_uvalue (logbuffer, partially_covered);
3166
3167         EXIT_LOG;
3168
3169         g_free (class_name);
3170 }
3171
3172 static void
3173 get_coverage_for_image (MonoImage *image, int *number_of_methods, guint *fully_covered, int *partially_covered)
3174 {
3175         MonoLockFreeQueue *image_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (log_profiler.coverage_image_to_methods, image);
3176
3177         *number_of_methods = mono_image_get_table_rows (image, MONO_TABLE_METHOD);
3178         if (image_methods)
3179                 *fully_covered = count_queue (image_methods);
3180         else
3181                 *fully_covered = 0;
3182
3183         // FIXME: We don't handle partially covered yet.
3184         *partially_covered = 0;
3185 }
3186
3187 static void
3188 build_assembly_buffer (gpointer key, gpointer value, gpointer userdata)
3189 {
3190         MonoAssembly *assembly = (MonoAssembly *)value;
3191         MonoImage *image = mono_assembly_get_image (assembly);
3192         const char *name, *guid, *filename;
3193         int number_of_methods = 0, partially_covered = 0;
3194         guint fully_covered = 0;
3195
3196         name = mono_image_get_name (image);
3197         guid = mono_image_get_guid (image);
3198         filename = mono_image_get_filename (image);
3199
3200         name = name ? name : "";
3201         guid = guid ? guid : "";
3202         filename = filename ? filename : "";
3203
3204         get_coverage_for_image (image, &number_of_methods, &fully_covered, &partially_covered);
3205
3206         ENTER_LOG (&coverage_assemblies_ctr, logbuffer,
3207                 EVENT_SIZE /* event */ +
3208                 strlen (name) + 1 /* name */ +
3209                 strlen (guid) + 1 /* guid */ +
3210                 strlen (filename) + 1 /* file name */ +
3211                 LEB128_SIZE /* no. methods */ +
3212                 LEB128_SIZE /* fully covered */ +
3213                 LEB128_SIZE /* partially covered */
3214         );
3215
3216         emit_event (logbuffer, TYPE_COVERAGE_ASSEMBLY | TYPE_COVERAGE);
3217         emit_string (logbuffer, name, strlen (name) + 1);
3218         emit_string (logbuffer, guid, strlen (guid) + 1);
3219         emit_string (logbuffer, filename, strlen (filename) + 1);
3220         emit_uvalue (logbuffer, number_of_methods);
3221         emit_uvalue (logbuffer, fully_covered);
3222         emit_uvalue (logbuffer, partially_covered);
3223
3224         EXIT_LOG;
3225 }
3226
3227 static void
3228 dump_coverage (void)
3229 {
3230         mono_os_mutex_lock (&log_profiler.coverage_mutex);
3231         mono_conc_hashtable_foreach (log_profiler.coverage_assemblies, build_assembly_buffer, NULL);
3232         mono_conc_hashtable_foreach (log_profiler.coverage_classes, build_class_buffer, NULL);
3233         mono_conc_hashtable_foreach (log_profiler.coverage_methods, build_method_buffer, NULL);
3234         mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3235 }
3236
3237 static MonoLockFreeQueueNode *
3238 create_method_node (MonoMethod *method)
3239 {
3240         MethodNode *node = (MethodNode *) g_malloc (sizeof (MethodNode));
3241         mono_lock_free_queue_node_init ((MonoLockFreeQueueNode *) node, FALSE);
3242         node->method = method;
3243
3244         return (MonoLockFreeQueueNode *) node;
3245 }
3246
3247 static gboolean
3248 coverage_filter (MonoProfiler *prof, MonoMethod *method)
3249 {
3250         MonoError error;
3251         MonoClass *klass;
3252         MonoImage *image;
3253         MonoAssembly *assembly;
3254         MonoMethodHeader *header;
3255         guint32 iflags, flags, code_size;
3256         char *fqn, *classname;
3257         gboolean has_positive, found;
3258         MonoLockFreeQueue *image_methods, *class_methods;
3259         MonoLockFreeQueueNode *node;
3260
3261         flags = mono_method_get_flags (method, &iflags);
3262         if ((iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
3263             (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
3264                 return FALSE;
3265
3266         // Don't need to do anything else if we're already tracking this method
3267         if (mono_conc_hashtable_lookup (log_profiler.coverage_methods, method))
3268                 return TRUE;
3269
3270         klass = mono_method_get_class (method);
3271         image = mono_class_get_image (klass);
3272
3273         // Don't handle coverage for the core assemblies
3274         if (mono_conc_hashtable_lookup (log_profiler.coverage_suppressed_assemblies, (gpointer) mono_image_get_name (image)) != NULL)
3275                 return FALSE;
3276
3277         if (prof->coverage_filters) {
3278                 /* Check already filtered classes first */
3279                 if (mono_conc_hashtable_lookup (log_profiler.coverage_filtered_classes, klass))
3280                         return FALSE;
3281
3282                 classname = mono_type_get_name (mono_class_get_type (klass));
3283
3284                 fqn = g_strdup_printf ("[%s]%s", mono_image_get_name (image), classname);
3285
3286                 // Check positive filters first
3287                 has_positive = FALSE;
3288                 found = FALSE;
3289                 for (guint i = 0; i < prof->coverage_filters->len; ++i) {
3290                         char *filter = (char *)g_ptr_array_index (prof->coverage_filters, i);
3291
3292                         if (filter [0] == '+') {
3293                                 filter = &filter [1];
3294
3295                                 if (strstr (fqn, filter) != NULL)
3296                                         found = TRUE;
3297
3298                                 has_positive = TRUE;
3299                         }
3300                 }
3301
3302                 if (has_positive && !found) {
3303                         mono_os_mutex_lock (&log_profiler.coverage_mutex);
3304                         mono_conc_hashtable_insert (log_profiler.coverage_filtered_classes, klass, klass);
3305                         mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3306                         g_free (fqn);
3307                         g_free (classname);
3308
3309                         return FALSE;
3310                 }
3311
3312                 for (guint i = 0; i < prof->coverage_filters->len; ++i) {
3313                         // FIXME: Is substring search sufficient?
3314                         char *filter = (char *)g_ptr_array_index (prof->coverage_filters, i);
3315                         if (filter [0] == '+')
3316                                 continue;
3317
3318                         // Skip '-'
3319                         filter = &filter [1];
3320
3321                         if (strstr (fqn, filter) != NULL) {
3322                                 mono_os_mutex_lock (&log_profiler.coverage_mutex);
3323                                 mono_conc_hashtable_insert (log_profiler.coverage_filtered_classes, klass, klass);
3324                                 mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3325                                 g_free (fqn);
3326                                 g_free (classname);
3327
3328                                 return FALSE;
3329                         }
3330                 }
3331
3332                 g_free (fqn);
3333                 g_free (classname);
3334         }
3335
3336         header = mono_method_get_header_checked (method, &error);
3337         mono_error_cleanup (&error);
3338
3339         mono_method_header_get_code (header, &code_size, NULL);
3340
3341         assembly = mono_image_get_assembly (image);
3342
3343         // Need to keep the assemblies around for as long as they are kept in the hashtable
3344         // Nunit, for example, has a habit of unloading them before the coverage statistics are
3345         // generated causing a crash. See https://bugzilla.xamarin.com/show_bug.cgi?id=39325
3346         mono_assembly_addref (assembly);
3347
3348         mono_os_mutex_lock (&log_profiler.coverage_mutex);
3349         mono_conc_hashtable_insert (log_profiler.coverage_methods, method, method);
3350         mono_conc_hashtable_insert (log_profiler.coverage_assemblies, assembly, assembly);
3351         mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3352
3353         image_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (log_profiler.coverage_image_to_methods, image);
3354
3355         if (image_methods == NULL) {
3356                 image_methods = (MonoLockFreeQueue *) g_malloc (sizeof (MonoLockFreeQueue));
3357                 mono_lock_free_queue_init (image_methods);
3358                 mono_os_mutex_lock (&log_profiler.coverage_mutex);
3359                 mono_conc_hashtable_insert (log_profiler.coverage_image_to_methods, image, image_methods);
3360                 mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3361         }
3362
3363         node = create_method_node (method);
3364         mono_lock_free_queue_enqueue (image_methods, node);
3365
3366         class_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (log_profiler.coverage_classes, klass);
3367
3368         if (class_methods == NULL) {
3369                 class_methods = (MonoLockFreeQueue *) g_malloc (sizeof (MonoLockFreeQueue));
3370                 mono_lock_free_queue_init (class_methods);
3371                 mono_os_mutex_lock (&log_profiler.coverage_mutex);
3372                 mono_conc_hashtable_insert (log_profiler.coverage_classes, klass, class_methods);
3373                 mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3374         }
3375
3376         node = create_method_node (method);
3377         mono_lock_free_queue_enqueue (class_methods, node);
3378
3379         return TRUE;
3380 }
3381
3382 #define LINE_BUFFER_SIZE 4096
3383 /* Max file limit of 128KB */
3384 #define MAX_FILE_SIZE 128 * 1024
3385 static char *
3386 get_file_content (FILE *stream)
3387 {
3388         char *buffer;
3389         ssize_t bytes_read;
3390         long filesize;
3391         int res, offset = 0;
3392
3393         res = fseek (stream, 0, SEEK_END);
3394         if (res < 0)
3395           return NULL;
3396
3397         filesize = ftell (stream);
3398         if (filesize < 0)
3399           return NULL;
3400
3401         res = fseek (stream, 0, SEEK_SET);
3402         if (res < 0)
3403           return NULL;
3404
3405         if (filesize > MAX_FILE_SIZE)
3406           return NULL;
3407
3408         buffer = (char *) g_malloc ((filesize + 1) * sizeof (char));
3409         while ((bytes_read = fread (buffer + offset, 1, LINE_BUFFER_SIZE, stream)) > 0)
3410                 offset += bytes_read;
3411
3412         /* NULL terminate our buffer */
3413         buffer[filesize] = '\0';
3414         return buffer;
3415 }
3416
3417 static char *
3418 get_next_line (char *contents, char **next_start)
3419 {
3420         char *p = contents;
3421
3422         if (p == NULL || *p == '\0') {
3423                 *next_start = NULL;
3424                 return NULL;
3425         }
3426
3427         while (*p != '\n' && *p != '\0')
3428                 p++;
3429
3430         if (*p == '\n') {
3431                 *p = '\0';
3432                 *next_start = p + 1;
3433         } else
3434                 *next_start = NULL;
3435
3436         return contents;
3437 }
3438
3439 static void
3440 init_suppressed_assemblies (void)
3441 {
3442         char *content;
3443         char *line;
3444         FILE *sa_file;
3445
3446         log_profiler.coverage_suppressed_assemblies = mono_conc_hashtable_new (g_str_hash, g_str_equal);
3447         sa_file = fopen (SUPPRESSION_DIR "/mono-profiler-log.suppression", "r");
3448         if (sa_file == NULL)
3449                 return;
3450
3451         /* Don't need to free @content as it is referred to by the lines stored in @suppressed_assemblies */
3452         content = get_file_content (sa_file);
3453         if (content == NULL)
3454                 g_error ("mono-profiler-log.suppression is greater than 128kb - aborting.");
3455
3456         while ((line = get_next_line (content, &content))) {
3457                 line = g_strchomp (g_strchug (line));
3458                 /* No locking needed as we're doing initialization */
3459                 mono_conc_hashtable_insert (log_profiler.coverage_suppressed_assemblies, line, line);
3460         }
3461
3462         fclose (sa_file);
3463 }
3464
3465 static void
3466 parse_cov_filter_file (GPtrArray *filters, const char *file)
3467 {
3468         FILE *filter_file = fopen (file, "r");
3469
3470         if (filter_file == NULL) {
3471                 mono_profiler_printf_err ("Could not open coverage filter file '%s'.", file);
3472                 return;
3473         }
3474
3475         /* Don't need to free content as it is referred to by the lines stored in @filters */
3476         char *content = get_file_content (filter_file);
3477
3478         if (content == NULL)
3479                 mono_profiler_printf_err ("Coverage filter file '%s' is larger than 128kb - ignoring.", file);
3480
3481         char *line;
3482
3483         while ((line = get_next_line (content, &content)))
3484                 g_ptr_array_add (filters, g_strchug (g_strchomp (line)));
3485
3486         fclose (filter_file);
3487 }
3488
3489 static void
3490 coverage_init (void)
3491 {
3492         mono_os_mutex_init (&log_profiler.coverage_mutex);
3493         log_profiler.coverage_methods = mono_conc_hashtable_new (NULL, NULL);
3494         log_profiler.coverage_assemblies = mono_conc_hashtable_new (NULL, NULL);
3495         log_profiler.coverage_classes = mono_conc_hashtable_new (NULL, NULL);
3496         log_profiler.coverage_filtered_classes = mono_conc_hashtable_new (NULL, NULL);
3497         log_profiler.coverage_image_to_methods = mono_conc_hashtable_new (NULL, NULL);
3498         init_suppressed_assemblies ();
3499 }
3500
3501 static void
3502 unref_coverage_assemblies (gpointer key, gpointer value, gpointer userdata)
3503 {
3504         MonoAssembly *assembly = (MonoAssembly *)value;
3505         mono_assembly_close (assembly);
3506 }
3507
3508 static void
3509 free_sample_hit (gpointer p)
3510 {
3511         mono_lock_free_free (p, SAMPLE_BLOCK_SIZE);
3512 }
3513
3514 static void
3515 cleanup_reusable_samples (void)
3516 {
3517         SampleHit *sample;
3518
3519         while ((sample = (SampleHit *) mono_lock_free_queue_dequeue (&log_profiler.sample_reuse_queue)))
3520                 mono_thread_hazardous_try_free (sample, free_sample_hit);
3521 }
3522
3523 static void
3524 log_early_shutdown (MonoProfiler *prof)
3525 {
3526         if (log_config.hs_on_shutdown) {
3527                 InterlockedWrite (&log_profiler.heapshot_requested, 1);
3528                 mono_gc_collect (mono_gc_max_generation ());
3529         }
3530 }
3531
3532 static void
3533 log_shutdown (MonoProfiler *prof)
3534 {
3535         InterlockedWrite (&log_profiler.in_shutdown, 1);
3536
3537         if (ENABLED (PROFLOG_COUNTER_EVENTS))
3538                 counters_and_perfcounters_sample ();
3539
3540         if (log_config.collect_coverage)
3541                 dump_coverage ();
3542
3543         char c = 1;
3544
3545         if (write (prof->pipes [1], &c, 1) != 1) {
3546                 mono_profiler_printf_err ("Could not write to log profiler pipe: %s", g_strerror (errno));
3547                 exit (1);
3548         }
3549
3550         mono_native_thread_join (prof->helper_thread);
3551
3552         mono_os_mutex_destroy (&log_profiler.counters_mutex);
3553
3554         MonoCounterAgent *mc_next;
3555
3556         for (MonoCounterAgent *cur = log_profiler.counters; cur; cur = mc_next) {
3557                 mc_next = cur->next;
3558                 g_free (cur);
3559         }
3560
3561         PerfCounterAgent *pc_next;
3562
3563         for (PerfCounterAgent *cur = log_profiler.perfcounters; cur; cur = pc_next) {
3564                 pc_next = cur->next;
3565                 g_free (cur);
3566         }
3567
3568         /*
3569          * Ensure that we empty the LLS completely, even if some nodes are
3570          * not immediately removed upon calling mono_lls_remove (), by
3571          * iterating until the head is NULL.
3572          */
3573         while (log_profiler.profiler_thread_list.head) {
3574                 MONO_LLS_FOREACH_SAFE (&log_profiler.profiler_thread_list, MonoProfilerThread, thread) {
3575                         g_assert (thread->attached && "Why is a thread in the LLS not attached?");
3576
3577                         remove_thread (thread);
3578                 } MONO_LLS_FOREACH_SAFE_END
3579         }
3580
3581         /*
3582          * Ensure that all threads have been freed, so that we don't miss any
3583          * buffers when we shut down the writer thread below.
3584          */
3585         mono_thread_hazardous_try_free_all ();
3586
3587         InterlockedWrite (&prof->run_dumper_thread, 0);
3588         mono_os_sem_post (&prof->dumper_queue_sem);
3589         mono_native_thread_join (prof->dumper_thread);
3590         mono_os_sem_destroy (&prof->dumper_queue_sem);
3591
3592         InterlockedWrite (&prof->run_writer_thread, 0);
3593         mono_os_sem_post (&prof->writer_queue_sem);
3594         mono_native_thread_join (prof->writer_thread);
3595         mono_os_sem_destroy (&prof->writer_queue_sem);
3596
3597         /*
3598          * Free all writer queue entries, and ensure that all sample hits will be
3599          * added to the sample reuse queue.
3600          */
3601         mono_thread_hazardous_try_free_all ();
3602
3603         cleanup_reusable_samples ();
3604
3605         /*
3606          * Finally, make sure that all sample hits are freed. This should cover all
3607          * hazardous data from the profiler. We can now be sure that the runtime
3608          * won't later invoke free functions in the profiler library after it has
3609          * been unloaded.
3610          */
3611         mono_thread_hazardous_try_free_all ();
3612
3613         gint32 state = InterlockedRead (&log_profiler.buffer_lock_state);
3614
3615         g_assert (!(state & 0xFFFF) && "Why is the reader count still non-zero?");
3616         g_assert (!(state >> 16) && "Why is the exclusive lock still held?");
3617
3618 #if defined (HAVE_SYS_ZLIB)
3619         if (prof->gzfile)
3620                 gzclose (prof->gzfile);
3621 #endif
3622         if (prof->pipe_output)
3623                 pclose (prof->file);
3624         else
3625                 fclose (prof->file);
3626
3627         mono_conc_hashtable_destroy (prof->method_table);
3628         mono_os_mutex_destroy (&prof->method_table_mutex);
3629
3630         if (log_config.collect_coverage) {
3631                 mono_os_mutex_lock (&log_profiler.coverage_mutex);
3632                 mono_conc_hashtable_foreach (log_profiler.coverage_assemblies, unref_coverage_assemblies, NULL);
3633                 mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3634
3635                 mono_conc_hashtable_destroy (log_profiler.coverage_methods);
3636                 mono_conc_hashtable_destroy (log_profiler.coverage_assemblies);
3637                 mono_conc_hashtable_destroy (log_profiler.coverage_classes);
3638                 mono_conc_hashtable_destroy (log_profiler.coverage_filtered_classes);
3639
3640                 mono_conc_hashtable_destroy (log_profiler.coverage_image_to_methods);
3641                 mono_conc_hashtable_destroy (log_profiler.coverage_suppressed_assemblies);
3642                 mono_os_mutex_destroy (&log_profiler.coverage_mutex);
3643         }
3644
3645         mono_coop_mutex_destroy (&log_profiler.api_mutex);
3646
3647         PROF_TLS_FREE ();
3648
3649         g_free (prof->args);
3650 }
3651
3652 static char*
3653 new_filename (const char* filename)
3654 {
3655         time_t t = time (NULL);
3656         int pid = process_id ();
3657         char pid_buf [16];
3658         char time_buf [16];
3659         char *res, *d;
3660         const char *p;
3661         int count_dates = 0;
3662         int count_pids = 0;
3663         int s_date, s_pid;
3664         struct tm *ts;
3665         for (p = filename; *p; p++) {
3666                 if (*p != '%')
3667                         continue;
3668                 p++;
3669                 if (*p == 't')
3670                         count_dates++;
3671                 else if (*p == 'p')
3672                         count_pids++;
3673                 else if (*p == 0)
3674                         break;
3675         }
3676         if (!count_dates && !count_pids)
3677                 return pstrdup (filename);
3678         snprintf (pid_buf, sizeof (pid_buf), "%d", pid);
3679         ts = gmtime (&t);
3680         snprintf (time_buf, sizeof (time_buf), "%d%02d%02d%02d%02d%02d",
3681                 1900 + ts->tm_year, 1 + ts->tm_mon, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec);
3682         s_date = strlen (time_buf);
3683         s_pid = strlen (pid_buf);
3684         d = res = (char *) g_malloc (strlen (filename) + s_date * count_dates + s_pid * count_pids);
3685         for (p = filename; *p; p++) {
3686                 if (*p != '%') {
3687                         *d++ = *p;
3688                         continue;
3689                 }
3690                 p++;
3691                 if (*p == 't') {
3692                         strcpy (d, time_buf);
3693                         d += s_date;
3694                         continue;
3695                 } else if (*p == 'p') {
3696                         strcpy (d, pid_buf);
3697                         d += s_pid;
3698                         continue;
3699                 } else if (*p == '%') {
3700                         *d++ = '%';
3701                         continue;
3702                 } else if (*p == 0)
3703                         break;
3704                 *d++ = '%';
3705                 *d++ = *p;
3706         }
3707         *d = 0;
3708         return res;
3709 }
3710
3711 static void
3712 add_to_fd_set (fd_set *set, int fd, int *max_fd)
3713 {
3714         /*
3715          * This should only trigger for the basic FDs (server socket, pipes) at
3716          * startup if for some mysterious reason they're too large. In this case,
3717          * the profiler really can't function, and we're better off printing an
3718          * error and exiting.
3719          */
3720         if (fd >= FD_SETSIZE) {
3721                 mono_profiler_printf_err ("File descriptor is out of bounds for fd_set: %d", fd);
3722                 exit (1);
3723         }
3724
3725         FD_SET (fd, set);
3726
3727         if (*max_fd < fd)
3728                 *max_fd = fd;
3729 }
3730
3731 static void *
3732 helper_thread (void *arg)
3733 {
3734         mono_threads_attach_tools_thread ();
3735         mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler helper");
3736
3737         MonoProfilerThread *thread = init_thread (FALSE);
3738
3739         GArray *command_sockets = g_array_new (FALSE, FALSE, sizeof (int));
3740
3741         while (1) {
3742                 fd_set rfds;
3743                 int max_fd = -1;
3744
3745                 FD_ZERO (&rfds);
3746
3747                 add_to_fd_set (&rfds, log_profiler.server_socket, &max_fd);
3748                 add_to_fd_set (&rfds, log_profiler.pipes [0], &max_fd);
3749
3750                 for (gint i = 0; i < command_sockets->len; i++)
3751                         add_to_fd_set (&rfds, g_array_index (command_sockets, int, i), &max_fd);
3752
3753                 struct timeval tv = { .tv_sec = 1, .tv_usec = 0 };
3754
3755                 // Sleep for 1sec or until a file descriptor has data.
3756                 if (select (max_fd + 1, &rfds, NULL, NULL, &tv) == -1) {
3757                         if (errno == EINTR)
3758                                 continue;
3759
3760                         mono_profiler_printf_err ("Could not poll in log profiler helper thread: %s", g_strerror (errno));
3761                         exit (1);
3762                 }
3763
3764                 if (ENABLED (PROFLOG_COUNTER_EVENTS))
3765                         counters_and_perfcounters_sample ();
3766
3767                 buffer_lock_excl ();
3768
3769                 sync_point (SYNC_POINT_PERIODIC);
3770
3771                 buffer_unlock_excl ();
3772
3773                 // Are we shutting down?
3774                 if (FD_ISSET (log_profiler.pipes [0], &rfds)) {
3775                         char c;
3776                         read (log_profiler.pipes [0], &c, 1);
3777                         break;
3778                 }
3779
3780                 for (gint i = 0; i < command_sockets->len; i++) {
3781                         int fd = g_array_index (command_sockets, int, i);
3782
3783                         if (!FD_ISSET (fd, &rfds))
3784                                 continue;
3785
3786                         char buf [64];
3787                         int len = read (fd, buf, sizeof (buf) - 1);
3788
3789                         if (len == -1)
3790                                 continue;
3791
3792                         if (!len) {
3793                                 // The other end disconnected.
3794                                 g_array_remove_index (command_sockets, i);
3795                                 close (fd);
3796
3797                                 continue;
3798                         }
3799
3800                         buf [len] = 0;
3801
3802                         if (log_config.hs_mode == MONO_PROFILER_HEAPSHOT_ON_DEMAND && !strcmp (buf, "heapshot\n")) {
3803                                 // Rely on the finalization callback triggering a GC.
3804                                 InterlockedWrite (&log_profiler.heapshot_requested, 1);
3805                                 mono_gc_finalize_notify ();
3806                         }
3807                 }
3808
3809                 if (FD_ISSET (log_profiler.server_socket, &rfds)) {
3810                         int fd = accept (log_profiler.server_socket, NULL, NULL);
3811
3812                         if (fd != -1) {
3813                                 if (fd >= FD_SETSIZE)
3814                                         close (fd);
3815                                 else
3816                                         g_array_append_val (command_sockets, fd);
3817                         }
3818                 }
3819         }
3820
3821         for (gint i = 0; i < command_sockets->len; i++)
3822                 close (g_array_index (command_sockets, int, i));
3823
3824         g_array_free (command_sockets, TRUE);
3825
3826         send_log_unsafe (FALSE);
3827         deinit_thread (thread);
3828
3829         mono_thread_info_detach ();
3830
3831         return NULL;
3832 }
3833
3834 static void
3835 start_helper_thread (void)
3836 {
3837         if (pipe (log_profiler.pipes) == -1) {
3838                 mono_profiler_printf_err ("Could not create log profiler pipe: %s", g_strerror (errno));
3839                 exit (1);
3840         }
3841
3842         log_profiler.server_socket = socket (PF_INET, SOCK_STREAM, 0);
3843
3844         if (log_profiler.server_socket == -1) {
3845                 mono_profiler_printf_err ("Could not create log profiler server socket: %s", g_strerror (errno));
3846                 exit (1);
3847         }
3848
3849         struct sockaddr_in server_address;
3850
3851         memset (&server_address, 0, sizeof (server_address));
3852         server_address.sin_family = AF_INET;
3853         server_address.sin_addr.s_addr = INADDR_ANY;
3854         server_address.sin_port = htons (log_profiler.command_port);
3855
3856         if (bind (log_profiler.server_socket, (struct sockaddr *) &server_address, sizeof (server_address)) == -1) {
3857                 mono_profiler_printf_err ("Could not bind log profiler server socket on port %d: %s", log_profiler.command_port, g_strerror (errno));
3858                 close (log_profiler.server_socket);
3859                 exit (1);
3860         }
3861
3862         if (listen (log_profiler.server_socket, 1) == -1) {
3863                 mono_profiler_printf_err ("Could not listen on log profiler server socket: %s", g_strerror (errno));
3864                 close (log_profiler.server_socket);
3865                 exit (1);
3866         }
3867
3868         socklen_t slen = sizeof (server_address);
3869
3870         if (getsockname (log_profiler.server_socket, (struct sockaddr *) &server_address, &slen)) {
3871                 mono_profiler_printf_err ("Could not retrieve assigned port for log profiler server socket: %s", g_strerror (errno));
3872                 close (log_profiler.server_socket);
3873                 exit (1);
3874         }
3875
3876         log_profiler.command_port = ntohs (server_address.sin_port);
3877
3878         if (!mono_native_thread_create (&log_profiler.helper_thread, helper_thread, NULL)) {
3879                 mono_profiler_printf_err ("Could not start log profiler helper thread");
3880                 close (log_profiler.server_socket);
3881                 exit (1);
3882         }
3883 }
3884
3885 static void
3886 free_writer_entry (gpointer p)
3887 {
3888         mono_lock_free_free (p, WRITER_ENTRY_BLOCK_SIZE);
3889 }
3890
3891 static gboolean
3892 handle_writer_queue_entry (void)
3893 {
3894         WriterQueueEntry *entry;
3895
3896         if ((entry = (WriterQueueEntry *) mono_lock_free_queue_dequeue (&log_profiler.writer_queue))) {
3897                 if (!entry->methods)
3898                         goto no_methods;
3899
3900                 gboolean wrote_methods = FALSE;
3901
3902                 /*
3903                  * Encode the method events in a temporary log buffer that we
3904                  * flush to disk before the main buffer, ensuring that all
3905                  * methods have metadata emitted before they're referenced.
3906                  *
3907                  * We use a 'proper' thread-local buffer for this as opposed
3908                  * to allocating and freeing a buffer by hand because the call
3909                  * to mono_method_full_name () below may trigger class load
3910                  * events when it retrieves the signature of the method. So a
3911                  * thread-local buffer needs to exist when such events occur.
3912                  */
3913                 for (guint i = 0; i < entry->methods->len; i++) {
3914                         MethodInfo *info = (MethodInfo *) g_ptr_array_index (entry->methods, i);
3915
3916                         if (mono_conc_hashtable_lookup (log_profiler.method_table, info->method))
3917                                 goto free_info; // This method already has metadata emitted.
3918
3919                         /*
3920                          * Other threads use this hash table to get a general
3921                          * idea of whether a method has already been emitted to
3922                          * the stream. Due to the way we add to this table, it
3923                          * can easily happen that multiple threads queue up the
3924                          * same methods, but that's OK since eventually all
3925                          * methods will be in this table and the thread-local
3926                          * method lists will just be empty for the rest of the
3927                          * app's lifetime.
3928                          */
3929                         mono_os_mutex_lock (&log_profiler.method_table_mutex);
3930                         mono_conc_hashtable_insert (log_profiler.method_table, info->method, info->method);
3931                         mono_os_mutex_unlock (&log_profiler.method_table_mutex);
3932
3933                         char *name = mono_method_full_name (info->method, 1);
3934                         int nlen = strlen (name) + 1;
3935                         void *cstart = info->ji ? mono_jit_info_get_code_start (info->ji) : NULL;
3936                         int csize = info->ji ? mono_jit_info_get_code_size (info->ji) : 0;
3937
3938                         ENTER_LOG (&method_jits_ctr, logbuffer,
3939                                 EVENT_SIZE /* event */ +
3940                                 LEB128_SIZE /* method */ +
3941                                 LEB128_SIZE /* start */ +
3942                                 LEB128_SIZE /* size */ +
3943                                 nlen /* name */
3944                         );
3945
3946                         emit_event_time (logbuffer, TYPE_JIT | TYPE_METHOD, info->time);
3947                         emit_method_inner (logbuffer, info->method);
3948                         emit_ptr (logbuffer, cstart);
3949                         emit_value (logbuffer, csize);
3950
3951                         memcpy (logbuffer->cursor, name, nlen);
3952                         logbuffer->cursor += nlen;
3953
3954                         EXIT_LOG_EXPLICIT (NO_SEND);
3955
3956                         mono_free (name);
3957
3958                         wrote_methods = TRUE;
3959
3960                 free_info:
3961                         g_free (info);
3962                 }
3963
3964                 g_ptr_array_free (entry->methods, TRUE);
3965
3966                 if (wrote_methods) {
3967                         MonoProfilerThread *thread = PROF_TLS_GET ();
3968
3969                         dump_buffer_threadless (thread->buffer);
3970                         init_buffer_state (thread);
3971                 }
3972
3973         no_methods:
3974                 dump_buffer (entry->buffer);
3975
3976                 mono_thread_hazardous_try_free (entry, free_writer_entry);
3977
3978                 return TRUE;
3979         }
3980
3981         return FALSE;
3982 }
3983
3984 static void *
3985 writer_thread (void *arg)
3986 {
3987         mono_threads_attach_tools_thread ();
3988         mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler writer");
3989
3990         dump_header ();
3991
3992         MonoProfilerThread *thread = init_thread (FALSE);
3993
3994         while (InterlockedRead (&log_profiler.run_writer_thread)) {
3995                 mono_os_sem_wait (&log_profiler.writer_queue_sem, MONO_SEM_FLAGS_NONE);
3996                 handle_writer_queue_entry ();
3997         }
3998
3999         /* Drain any remaining entries on shutdown. */
4000         while (handle_writer_queue_entry ());
4001
4002         free_buffer (thread->buffer, thread->buffer->size);
4003         deinit_thread (thread);
4004
4005         mono_thread_info_detach ();
4006
4007         return NULL;
4008 }
4009
4010 static void
4011 start_writer_thread (void)
4012 {
4013         InterlockedWrite (&log_profiler.run_writer_thread, 1);
4014
4015         if (!mono_native_thread_create (&log_profiler.writer_thread, writer_thread, NULL)) {
4016                 mono_profiler_printf_err ("Could not start log profiler writer thread");
4017                 exit (1);
4018         }
4019 }
4020
4021 static void
4022 reuse_sample_hit (gpointer p)
4023 {
4024         SampleHit *sample = p;
4025
4026         mono_lock_free_queue_node_unpoison (&sample->node);
4027         mono_lock_free_queue_enqueue (&log_profiler.sample_reuse_queue, &sample->node);
4028 }
4029
4030 static gboolean
4031 handle_dumper_queue_entry (void)
4032 {
4033         SampleHit *sample;
4034
4035         if ((sample = (SampleHit *) mono_lock_free_queue_dequeue (&log_profiler.dumper_queue))) {
4036                 for (int i = 0; i < sample->count; ++i) {
4037                         MonoMethod *method = sample->frames [i].method;
4038                         MonoDomain *domain = sample->frames [i].domain;
4039                         void *address = sample->frames [i].base_address;
4040
4041                         if (!method) {
4042                                 g_assert (domain && "What happened to the domain pointer?");
4043                                 g_assert (address && "What happened to the instruction pointer?");
4044
4045                                 MonoJitInfo *ji = mono_jit_info_table_find (domain, (char *) address);
4046
4047                                 if (ji)
4048                                         sample->frames [i].method = mono_jit_info_get_method (ji);
4049                         }
4050                 }
4051
4052                 ENTER_LOG (&sample_hits_ctr, logbuffer,
4053                         EVENT_SIZE /* event */ +
4054                         LEB128_SIZE /* tid */ +
4055                         LEB128_SIZE /* count */ +
4056                         1 * (
4057                                 LEB128_SIZE /* ip */
4058                         ) +
4059                         LEB128_SIZE /* managed count */ +
4060                         sample->count * (
4061                                 LEB128_SIZE /* method */
4062                         )
4063                 );
4064
4065                 emit_event_time (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_HIT, sample->time);
4066                 emit_ptr (logbuffer, (void *) sample->tid);
4067                 emit_value (logbuffer, 1);
4068
4069                 // TODO: Actual native unwinding.
4070                 for (int i = 0; i < 1; ++i) {
4071                         emit_ptr (logbuffer, sample->ip);
4072                         add_code_pointer ((uintptr_t) sample->ip);
4073                 }
4074
4075                 /* new in data version 6 */
4076                 emit_uvalue (logbuffer, sample->count);
4077
4078                 for (int i = 0; i < sample->count; ++i)
4079                         emit_method (logbuffer, sample->frames [i].method);
4080
4081                 EXIT_LOG;
4082
4083                 mono_thread_hazardous_try_free (sample, reuse_sample_hit);
4084
4085                 dump_unmanaged_coderefs ();
4086         }
4087
4088         return FALSE;
4089 }
4090
4091 static void *
4092 dumper_thread (void *arg)
4093 {
4094         mono_threads_attach_tools_thread ();
4095         mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler dumper");
4096
4097         MonoProfilerThread *thread = init_thread (FALSE);
4098
4099         while (InterlockedRead (&log_profiler.run_dumper_thread)) {
4100                 /*
4101                  * Flush samples every second so it doesn't seem like the profiler is
4102                  * not working if the program is mostly idle.
4103                  */
4104                 if (mono_os_sem_timedwait (&log_profiler.dumper_queue_sem, 1000, MONO_SEM_FLAGS_NONE) == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT)
4105                         send_log_unsafe (FALSE);
4106
4107                 handle_dumper_queue_entry ();
4108         }
4109
4110         /* Drain any remaining entries on shutdown. */
4111         while (handle_dumper_queue_entry ());
4112
4113         send_log_unsafe (FALSE);
4114         deinit_thread (thread);
4115
4116         mono_thread_info_detach ();
4117
4118         return NULL;
4119 }
4120
4121 static void
4122 start_dumper_thread (void)
4123 {
4124         InterlockedWrite (&log_profiler.run_dumper_thread, 1);
4125
4126         if (!mono_native_thread_create (&log_profiler.dumper_thread, dumper_thread, NULL)) {
4127                 mono_profiler_printf_err ("Could not start log profiler dumper thread");
4128                 exit (1);
4129         }
4130 }
4131
4132 static void
4133 register_counter (const char *name, gint32 *counter)
4134 {
4135         mono_counters_register (name, MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, counter);
4136 }
4137
4138 ICALL_EXPORT gint32
4139 proflog_icall_GetMaxStackTraceFrames (void)
4140 {
4141         return MAX_FRAMES;
4142 }
4143
4144 ICALL_EXPORT gint32
4145 proflog_icall_GetStackTraceFrames (void)
4146 {
4147         return log_config.num_frames;
4148 }
4149
4150 ICALL_EXPORT void
4151 proflog_icall_SetStackTraceFrames (gint32 value)
4152 {
4153         log_config.num_frames = value;
4154 }
4155
4156 ICALL_EXPORT MonoProfilerHeapshotMode
4157 proflog_icall_GetHeapshotMode (void)
4158 {
4159         return log_config.hs_mode;
4160 }
4161
4162 ICALL_EXPORT void
4163 proflog_icall_SetHeapshotMode (MonoProfilerHeapshotMode value)
4164 {
4165         log_config.hs_mode = value;
4166 }
4167
4168 ICALL_EXPORT gint32
4169 proflog_icall_GetHeapshotMillisecondsFrequency (void)
4170 {
4171         return log_config.hs_freq_ms;
4172 }
4173
4174 ICALL_EXPORT void
4175 proflog_icall_SetHeapshotMillisecondsFrequency (gint32 value)
4176 {
4177         log_config.hs_freq_ms = value;
4178 }
4179
4180 ICALL_EXPORT gint32
4181 proflog_icall_GetHeapshotCollectionsFrequency (void)
4182 {
4183         return log_config.hs_freq_gc;
4184 }
4185
4186 ICALL_EXPORT void
4187 proflog_icall_SetHeapshotCollectionsFrequency (gint32 value)
4188 {
4189         log_config.hs_freq_gc = value;
4190 }
4191
4192 ICALL_EXPORT gint32
4193 proflog_icall_GetCallDepth (void)
4194 {
4195         return log_config.max_call_depth;
4196 }
4197
4198 ICALL_EXPORT void
4199 proflog_icall_SetCallDepth (gint32 value)
4200 {
4201         log_config.max_call_depth = value;
4202 }
4203
4204 ICALL_EXPORT void
4205 proflog_icall_GetSampleMode (MonoProfilerSampleMode *mode, gint32 *frequency)
4206 {
4207         uint32_t freq;
4208
4209         mono_profiler_get_sample_mode (log_profiler.handle, mode, &freq);
4210
4211         *frequency = freq;
4212 }
4213
4214 ICALL_EXPORT MonoBoolean
4215 proflog_icall_SetSampleMode (MonoProfilerSampleMode mode, gint32 frequency)
4216 {
4217         mono_coop_mutex_lock (&log_profiler.api_mutex);
4218
4219         mono_bool result = mono_profiler_set_sample_mode (log_profiler.handle, mode, frequency);
4220
4221         if (mode != MONO_PROFILER_SAMPLE_MODE_NONE) {
4222                 ENABLE (PROFLOG_SAMPLE_EVENTS);
4223                 mono_profiler_set_sample_hit_callback (log_profiler.handle, mono_sample_hit);
4224         } else {
4225                 DISABLE (PROFLOG_SAMPLE_EVENTS);
4226                 mono_profiler_set_sample_hit_callback (log_profiler.handle, NULL);
4227         }
4228
4229         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4230
4231         return result;
4232 }
4233
4234 ICALL_EXPORT MonoBoolean
4235 proflog_icall_GetExceptionEvents (void)
4236 {
4237         return ENABLED (PROFLOG_EXCEPTION_EVENTS);
4238 }
4239
4240 ICALL_EXPORT void
4241 proflog_icall_SetExceptionEvents (MonoBoolean value)
4242 {
4243         mono_coop_mutex_lock (&log_profiler.api_mutex);
4244
4245         if (value) {
4246                 ENABLE (PROFLOG_EXCEPTION_EVENTS);
4247                 mono_profiler_set_exception_throw_callback (log_profiler.handle, throw_exc);
4248                 mono_profiler_set_exception_clause_callback (log_profiler.handle, clause_exc);
4249         } else {
4250                 DISABLE (PROFLOG_EXCEPTION_EVENTS);
4251                 mono_profiler_set_exception_throw_callback (log_profiler.handle, NULL);
4252                 mono_profiler_set_exception_clause_callback (log_profiler.handle, NULL);
4253         }
4254
4255         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4256 }
4257
4258 ICALL_EXPORT MonoBoolean
4259 proflog_icall_GetMonitorEvents (void)
4260 {
4261         return ENABLED (PROFLOG_MONITOR_EVENTS);
4262 }
4263
4264 ICALL_EXPORT void
4265 proflog_icall_SetMonitorEvents (MonoBoolean value)
4266 {
4267         mono_coop_mutex_lock (&log_profiler.api_mutex);
4268
4269         if (value) {
4270                 ENABLE (PROFLOG_MONITOR_EVENTS);
4271                 mono_profiler_set_monitor_contention_callback (log_profiler.handle, monitor_contention);
4272                 mono_profiler_set_monitor_acquired_callback (log_profiler.handle, monitor_acquired);
4273                 mono_profiler_set_monitor_failed_callback (log_profiler.handle, monitor_failed);
4274         } else {
4275                 DISABLE (PROFLOG_MONITOR_EVENTS);
4276                 mono_profiler_set_monitor_contention_callback (log_profiler.handle, NULL);
4277                 mono_profiler_set_monitor_acquired_callback (log_profiler.handle, NULL);
4278                 mono_profiler_set_monitor_failed_callback (log_profiler.handle, NULL);
4279         }
4280
4281         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4282 }
4283
4284 ICALL_EXPORT MonoBoolean
4285 proflog_icall_GetGCEvents (void)
4286 {
4287         return ENABLED (PROFLOG_GC_EVENTS);
4288 }
4289
4290 ICALL_EXPORT void
4291 proflog_icall_SetGCEvents (MonoBoolean value)
4292 {
4293         mono_coop_mutex_lock (&log_profiler.api_mutex);
4294
4295         if (value)
4296                 ENABLE (PROFLOG_GC_EVENTS);
4297         else
4298                 DISABLE (PROFLOG_GC_EVENTS);
4299
4300         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4301 }
4302
4303 ICALL_EXPORT MonoBoolean
4304 proflog_icall_GetGCAllocationEvents (void)
4305 {
4306         return ENABLED (PROFLOG_GC_ALLOCATION_EVENTS);
4307 }
4308
4309 ICALL_EXPORT void
4310 proflog_icall_SetGCAllocationEvents (MonoBoolean value)
4311 {
4312         mono_coop_mutex_lock (&log_profiler.api_mutex);
4313
4314         if (value) {
4315                 ENABLE (PROFLOG_GC_ALLOCATION_EVENTS);
4316                 mono_profiler_set_gc_allocation_callback (log_profiler.handle, gc_alloc);
4317         } else {
4318                 DISABLE (PROFLOG_GC_ALLOCATION_EVENTS);
4319                 mono_profiler_set_gc_allocation_callback (log_profiler.handle, NULL);
4320         }
4321
4322         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4323 }
4324
4325 ICALL_EXPORT MonoBoolean
4326 proflog_icall_GetGCMoveEvents (void)
4327 {
4328         return ENABLED (PROFLOG_GC_MOVE_EVENTS);
4329 }
4330
4331 ICALL_EXPORT void
4332 proflog_icall_SetGCMoveEvents (MonoBoolean value)
4333 {
4334         mono_coop_mutex_lock (&log_profiler.api_mutex);
4335
4336         if (value) {
4337                 ENABLE (PROFLOG_GC_MOVE_EVENTS);
4338                 mono_profiler_set_gc_moves_callback (log_profiler.handle, gc_moves);
4339         } else {
4340                 DISABLE (PROFLOG_GC_MOVE_EVENTS);
4341                 mono_profiler_set_gc_moves_callback (log_profiler.handle, NULL);
4342         }
4343
4344         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4345 }
4346
4347 ICALL_EXPORT MonoBoolean
4348 proflog_icall_GetGCRootEvents (void)
4349 {
4350         return ENABLED (PROFLOG_GC_ROOT_EVENTS);
4351 }
4352
4353 ICALL_EXPORT void
4354 proflog_icall_SetGCRootEvents (MonoBoolean value)
4355 {
4356         mono_coop_mutex_lock (&log_profiler.api_mutex);
4357
4358         if (value)
4359                 ENABLE (PROFLOG_GC_ROOT_EVENTS);
4360         else
4361                 DISABLE (PROFLOG_GC_ROOT_EVENTS);
4362
4363         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4364 }
4365
4366 ICALL_EXPORT MonoBoolean
4367 proflog_icall_GetGCHandleEvents (void)
4368 {
4369         return ENABLED (PROFLOG_GC_HANDLE_EVENTS);
4370 }
4371
4372 ICALL_EXPORT void
4373 proflog_icall_SetGCHandleEvents (MonoBoolean value)
4374 {
4375         mono_coop_mutex_lock (&log_profiler.api_mutex);
4376
4377         if (value) {
4378                 ENABLE (PROFLOG_GC_HANDLE_EVENTS);
4379                 mono_profiler_set_gc_handle_created_callback (log_profiler.handle, gc_handle_created);
4380                 mono_profiler_set_gc_handle_deleted_callback (log_profiler.handle, gc_handle_deleted);
4381         } else {
4382                 DISABLE (PROFLOG_GC_HANDLE_EVENTS);
4383                 mono_profiler_set_gc_handle_created_callback (log_profiler.handle, NULL);
4384                 mono_profiler_set_gc_handle_deleted_callback (log_profiler.handle, NULL);
4385         }
4386
4387         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4388 }
4389
4390 ICALL_EXPORT MonoBoolean
4391 proflog_icall_GetGCFinalizationEvents (void)
4392 {
4393         return ENABLED (PROFLOG_GC_FINALIZATION_EVENTS);
4394 }
4395
4396 ICALL_EXPORT void
4397 proflog_icall_SetGCFinalizationEvents (MonoBoolean value)
4398 {
4399         mono_coop_mutex_lock (&log_profiler.api_mutex);
4400
4401         if (value) {
4402                 ENABLE (PROFLOG_GC_FINALIZATION_EVENTS);
4403                 mono_profiler_set_gc_finalizing_callback (log_profiler.handle, finalize_begin);
4404                 mono_profiler_set_gc_finalizing_object_callback (log_profiler.handle, finalize_object_begin);
4405                 mono_profiler_set_gc_finalized_object_callback (log_profiler.handle, finalize_object_end);
4406         } else {
4407                 DISABLE (PROFLOG_GC_FINALIZATION_EVENTS);
4408                 mono_profiler_set_gc_finalizing_callback (log_profiler.handle, NULL);
4409                 mono_profiler_set_gc_finalizing_object_callback (log_profiler.handle, NULL);
4410                 mono_profiler_set_gc_finalized_object_callback (log_profiler.handle, NULL);
4411         }
4412
4413         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4414 }
4415
4416 ICALL_EXPORT MonoBoolean
4417 proflog_icall_GetCounterEvents (void)
4418 {
4419         return ENABLED (PROFLOG_COUNTER_EVENTS);
4420 }
4421
4422 ICALL_EXPORT void
4423 proflog_icall_SetCounterEvents (MonoBoolean value)
4424 {
4425         mono_coop_mutex_lock (&log_profiler.api_mutex);
4426
4427         if (value)
4428                 ENABLE (PROFLOG_COUNTER_EVENTS);
4429         else
4430                 DISABLE (PROFLOG_COUNTER_EVENTS);
4431
4432         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4433 }
4434
4435 ICALL_EXPORT MonoBoolean
4436 proflog_icall_GetJitEvents (void)
4437 {
4438         return ENABLED (PROFLOG_JIT_EVENTS);
4439 }
4440
4441 ICALL_EXPORT void
4442 proflog_icall_SetJitEvents (MonoBoolean value)
4443 {
4444         mono_coop_mutex_lock (&log_profiler.api_mutex);
4445
4446         if (value) {
4447                 ENABLE (PROFLOG_JIT_EVENTS);
4448                 mono_profiler_set_jit_code_buffer_callback (log_profiler.handle, code_buffer_new);
4449         } else {
4450                 DISABLE (PROFLOG_JIT_EVENTS);
4451                 mono_profiler_set_jit_code_buffer_callback (log_profiler.handle, NULL);
4452         }
4453
4454         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4455 }
4456
4457 static void
4458 runtime_initialized (MonoProfiler *profiler)
4459 {
4460         InterlockedWrite (&log_profiler.runtime_inited, 1);
4461
4462         register_counter ("Sample events allocated", &sample_allocations_ctr);
4463         register_counter ("Log buffers allocated", &buffer_allocations_ctr);
4464
4465         register_counter ("Event: Sync points", &sync_points_ctr);
4466         register_counter ("Event: Heap objects", &heap_objects_ctr);
4467         register_counter ("Event: Heap starts", &heap_starts_ctr);
4468         register_counter ("Event: Heap ends", &heap_ends_ctr);
4469         register_counter ("Event: Heap roots", &heap_roots_ctr);
4470         register_counter ("Event: GC events", &gc_events_ctr);
4471         register_counter ("Event: GC resizes", &gc_resizes_ctr);
4472         register_counter ("Event: GC allocations", &gc_allocs_ctr);
4473         register_counter ("Event: GC moves", &gc_moves_ctr);
4474         register_counter ("Event: GC handle creations", &gc_handle_creations_ctr);
4475         register_counter ("Event: GC handle deletions", &gc_handle_deletions_ctr);
4476         register_counter ("Event: GC finalize starts", &finalize_begins_ctr);
4477         register_counter ("Event: GC finalize ends", &finalize_ends_ctr);
4478         register_counter ("Event: GC finalize object starts", &finalize_object_begins_ctr);
4479         register_counter ("Event: GC finalize object ends", &finalize_object_ends_ctr);
4480         register_counter ("Event: Image loads", &image_loads_ctr);
4481         register_counter ("Event: Image unloads", &image_unloads_ctr);
4482         register_counter ("Event: Assembly loads", &assembly_loads_ctr);
4483         register_counter ("Event: Assembly unloads", &assembly_unloads_ctr);
4484         register_counter ("Event: Class loads", &class_loads_ctr);
4485         register_counter ("Event: Class unloads", &class_unloads_ctr);
4486         register_counter ("Event: Method entries", &method_entries_ctr);
4487         register_counter ("Event: Method exits", &method_exits_ctr);
4488         register_counter ("Event: Method exception leaves", &method_exception_exits_ctr);
4489         register_counter ("Event: Method JITs", &method_jits_ctr);
4490         register_counter ("Event: Code buffers", &code_buffers_ctr);
4491         register_counter ("Event: Exception throws", &exception_throws_ctr);
4492         register_counter ("Event: Exception clauses", &exception_clauses_ctr);
4493         register_counter ("Event: Monitor events", &monitor_events_ctr);
4494         register_counter ("Event: Thread starts", &thread_starts_ctr);
4495         register_counter ("Event: Thread ends", &thread_ends_ctr);
4496         register_counter ("Event: Thread names", &thread_names_ctr);
4497         register_counter ("Event: Domain loads", &domain_loads_ctr);
4498         register_counter ("Event: Domain unloads", &domain_unloads_ctr);
4499         register_counter ("Event: Domain names", &domain_names_ctr);
4500         register_counter ("Event: Context loads", &context_loads_ctr);
4501         register_counter ("Event: Context unloads", &context_unloads_ctr);
4502         register_counter ("Event: Sample binaries", &sample_ubins_ctr);
4503         register_counter ("Event: Sample symbols", &sample_usyms_ctr);
4504         register_counter ("Event: Sample hits", &sample_hits_ctr);
4505         register_counter ("Event: Counter descriptors", &counter_descriptors_ctr);
4506         register_counter ("Event: Counter samples", &counter_samples_ctr);
4507         register_counter ("Event: Performance counter descriptors", &perfcounter_descriptors_ctr);
4508         register_counter ("Event: Performance counter samples", &perfcounter_samples_ctr);
4509         register_counter ("Event: Coverage methods", &coverage_methods_ctr);
4510         register_counter ("Event: Coverage statements", &coverage_statements_ctr);
4511         register_counter ("Event: Coverage classes", &coverage_classes_ctr);
4512         register_counter ("Event: Coverage assemblies", &coverage_assemblies_ctr);
4513
4514         counters_init ();
4515
4516         /*
4517          * We must start the helper thread before the writer thread. This is
4518          * because the helper thread sets up the command port which is written to
4519          * the log header by the writer thread.
4520          */
4521         start_helper_thread ();
4522         start_writer_thread ();
4523         start_dumper_thread ();
4524
4525         mono_coop_mutex_init (&log_profiler.api_mutex);
4526
4527 #define ADD_ICALL(NAME) \
4528         mono_add_internal_call ("Mono.Profiler.Log.LogProfiler::" EGLIB_STRINGIFY (NAME), proflog_icall_ ## NAME);
4529
4530         ADD_ICALL (GetMaxStackTraceFrames);
4531         ADD_ICALL (GetStackTraceFrames);
4532         ADD_ICALL (SetStackTraceFrames);
4533         ADD_ICALL (GetHeapshotMode);
4534         ADD_ICALL (SetHeapshotMode);
4535         ADD_ICALL (GetHeapshotMillisecondsFrequency);
4536         ADD_ICALL (SetHeapshotMillisecondsFrequency);
4537         ADD_ICALL (GetHeapshotCollectionsFrequency);
4538         ADD_ICALL (SetHeapshotCollectionsFrequency);
4539         ADD_ICALL (GetCallDepth);
4540         ADD_ICALL (SetCallDepth);
4541         ADD_ICALL (GetSampleMode);
4542         ADD_ICALL (SetSampleMode);
4543         ADD_ICALL (GetExceptionEvents);
4544         ADD_ICALL (SetExceptionEvents);
4545         ADD_ICALL (GetMonitorEvents);
4546         ADD_ICALL (SetMonitorEvents);
4547         ADD_ICALL (GetGCEvents);
4548         ADD_ICALL (SetGCEvents);
4549         ADD_ICALL (GetGCAllocationEvents);
4550         ADD_ICALL (SetGCAllocationEvents);
4551         ADD_ICALL (GetGCMoveEvents);
4552         ADD_ICALL (SetGCMoveEvents);
4553         ADD_ICALL (GetGCRootEvents);
4554         ADD_ICALL (SetGCRootEvents);
4555         ADD_ICALL (GetGCHandleEvents);
4556         ADD_ICALL (SetGCHandleEvents);
4557         ADD_ICALL (GetGCFinalizationEvents);
4558         ADD_ICALL (SetGCFinalizationEvents);
4559         ADD_ICALL (GetCounterEvents);
4560         ADD_ICALL (SetCounterEvents);
4561         ADD_ICALL (GetJitEvents);
4562         ADD_ICALL (SetJitEvents);
4563
4564 #undef ADD_ICALL
4565 }
4566
4567 static void
4568 create_profiler (const char *args, const char *filename, GPtrArray *filters)
4569 {
4570         char *nf;
4571
4572         log_profiler.args = pstrdup (args);
4573         log_profiler.command_port = log_config.command_port;
4574
4575         //If filename begin with +, append the pid at the end
4576         if (filename && *filename == '+')
4577                 filename = g_strdup_printf ("%s.%d", filename + 1, getpid ());
4578
4579         if (!filename) {
4580                 if (log_config.do_report)
4581                         filename = "|mprof-report -";
4582                 else
4583                         filename = "output.mlpd";
4584                 nf = (char*)filename;
4585         } else {
4586                 nf = new_filename (filename);
4587                 if (log_config.do_report) {
4588                         int s = strlen (nf) + 32;
4589                         char *p = (char *) g_malloc (s);
4590                         snprintf (p, s, "|mprof-report '--out=%s' -", nf);
4591                         g_free (nf);
4592                         nf = p;
4593                 }
4594         }
4595         if (*nf == '|') {
4596                 log_profiler.file = popen (nf + 1, "w");
4597                 log_profiler.pipe_output = 1;
4598         } else if (*nf == '#') {
4599                 int fd = strtol (nf + 1, NULL, 10);
4600                 log_profiler.file = fdopen (fd, "a");
4601         } else
4602                 log_profiler.file = fopen (nf, "wb");
4603
4604         if (!log_profiler.file) {
4605                 mono_profiler_printf_err ("Could not create log profiler output file '%s'.", nf);
4606                 exit (1);
4607         }
4608
4609 #if defined (HAVE_SYS_ZLIB)
4610         if (log_config.use_zip)
4611                 log_profiler.gzfile = gzdopen (fileno (log_profiler.file), "wb");
4612 #endif
4613
4614         /*
4615          * If you hit this assert while increasing MAX_FRAMES, you need to increase
4616          * SAMPLE_BLOCK_SIZE as well.
4617          */
4618         g_assert (SAMPLE_SLOT_SIZE (MAX_FRAMES) * 2 < LOCK_FREE_ALLOC_SB_USABLE_SIZE (SAMPLE_BLOCK_SIZE));
4619
4620         // FIXME: We should free this stuff too.
4621         mono_lock_free_allocator_init_size_class (&log_profiler.sample_size_class, SAMPLE_SLOT_SIZE (log_config.num_frames), SAMPLE_BLOCK_SIZE);
4622         mono_lock_free_allocator_init_allocator (&log_profiler.sample_allocator, &log_profiler.sample_size_class, MONO_MEM_ACCOUNT_PROFILER);
4623
4624         mono_lock_free_queue_init (&log_profiler.sample_reuse_queue);
4625
4626         g_assert (sizeof (WriterQueueEntry) * 2 < LOCK_FREE_ALLOC_SB_USABLE_SIZE (WRITER_ENTRY_BLOCK_SIZE));
4627
4628         // FIXME: We should free this stuff too.
4629         mono_lock_free_allocator_init_size_class (&log_profiler.writer_entry_size_class, sizeof (WriterQueueEntry), WRITER_ENTRY_BLOCK_SIZE);
4630         mono_lock_free_allocator_init_allocator (&log_profiler.writer_entry_allocator, &log_profiler.writer_entry_size_class, MONO_MEM_ACCOUNT_PROFILER);
4631
4632         mono_lock_free_queue_init (&log_profiler.writer_queue);
4633         mono_os_sem_init (&log_profiler.writer_queue_sem, 0);
4634
4635         mono_lock_free_queue_init (&log_profiler.dumper_queue);
4636         mono_os_sem_init (&log_profiler.dumper_queue_sem, 0);
4637
4638         mono_os_mutex_init (&log_profiler.method_table_mutex);
4639         log_profiler.method_table = mono_conc_hashtable_new (NULL, NULL);
4640
4641         if (log_config.collect_coverage)
4642                 coverage_init ();
4643
4644         log_profiler.coverage_filters = filters;
4645
4646         log_profiler.startup_time = current_time ();
4647 }
4648
4649 MONO_API void
4650 mono_profiler_init_log (const char *desc);
4651
4652 void
4653 mono_profiler_init_log (const char *desc)
4654 {
4655         GPtrArray *filters = NULL;
4656
4657         proflog_parse_args (&log_config, desc [3] == ':' ? desc + 4 : "");
4658
4659         if (log_config.cov_filter_files) {
4660                 filters = g_ptr_array_new ();
4661                 int i;
4662                 for (i = 0; i < log_config.cov_filter_files->len; ++i) {
4663                         const char *name = log_config.cov_filter_files->pdata [i];
4664                         parse_cov_filter_file (filters, name);
4665                 }
4666         }
4667
4668         init_time ();
4669
4670         PROF_TLS_INIT ();
4671
4672         create_profiler (desc, log_config.output_filename, filters);
4673
4674         mono_lls_init (&log_profiler.profiler_thread_list, NULL);
4675
4676         MonoProfilerHandle handle = log_profiler.handle = mono_profiler_create (&log_profiler);
4677
4678         /*
4679          * Required callbacks. These are either necessary for the profiler itself
4680          * to function, or provide metadata that's needed if other events (e.g.
4681          * allocations, exceptions) are dynamically enabled/disabled.
4682          */
4683
4684         mono_profiler_set_runtime_shutdown_begin_callback (handle, log_early_shutdown);
4685         mono_profiler_set_runtime_shutdown_end_callback (handle, log_shutdown);
4686         mono_profiler_set_runtime_initialized_callback (handle, runtime_initialized);
4687
4688         mono_profiler_set_gc_event_callback (handle, gc_event);
4689
4690         mono_profiler_set_thread_started_callback (handle, thread_start);
4691         mono_profiler_set_thread_stopped_callback (handle, thread_end);
4692         mono_profiler_set_thread_name_callback (handle, thread_name);
4693
4694         mono_profiler_set_domain_loaded_callback (handle, domain_loaded);
4695         mono_profiler_set_domain_unloading_callback (handle, domain_unloaded);
4696         mono_profiler_set_domain_name_callback (handle, domain_name);
4697
4698         mono_profiler_set_context_loaded_callback (handle, context_loaded);
4699         mono_profiler_set_context_unloaded_callback (handle, context_unloaded);
4700
4701         mono_profiler_set_assembly_loaded_callback (handle, assembly_loaded);
4702         mono_profiler_set_assembly_unloading_callback (handle, assembly_unloaded);
4703
4704         mono_profiler_set_image_loaded_callback (handle, image_loaded);
4705         mono_profiler_set_image_unloading_callback (handle, image_unloaded);
4706
4707         mono_profiler_set_class_loaded_callback (handle, class_loaded);
4708
4709         mono_profiler_set_jit_done_callback (handle, method_jitted);
4710
4711         if (ENABLED (PROFLOG_EXCEPTION_EVENTS)) {
4712                 mono_profiler_set_exception_throw_callback (handle, throw_exc);
4713                 mono_profiler_set_exception_clause_callback (handle, clause_exc);
4714         }
4715
4716         if (ENABLED (PROFLOG_MONITOR_EVENTS)) {
4717                 mono_profiler_set_monitor_contention_callback (handle, monitor_contention);
4718                 mono_profiler_set_monitor_acquired_callback (handle, monitor_acquired);
4719                 mono_profiler_set_monitor_failed_callback (handle, monitor_failed);
4720         }
4721
4722         if (ENABLED (PROFLOG_GC_EVENTS))
4723                 mono_profiler_set_gc_resize_callback (handle, gc_resize);
4724
4725         if (ENABLED (PROFLOG_GC_ALLOCATION_EVENTS))
4726                 mono_profiler_set_gc_allocation_callback (handle, gc_alloc);
4727
4728         if (ENABLED (PROFLOG_GC_MOVE_EVENTS))
4729                 mono_profiler_set_gc_moves_callback (handle, gc_moves);
4730
4731         if (ENABLED (PROFLOG_GC_ROOT_EVENTS))
4732                 mono_profiler_set_gc_roots_callback (handle, gc_roots);
4733
4734         if (ENABLED (PROFLOG_GC_HANDLE_EVENTS)) {
4735                 mono_profiler_set_gc_handle_created_callback (handle, gc_handle_created);
4736                 mono_profiler_set_gc_handle_deleted_callback (handle, gc_handle_deleted);
4737         }
4738
4739         if (ENABLED (PROFLOG_GC_FINALIZATION_EVENTS)) {
4740                 mono_profiler_set_gc_finalizing_callback (handle, finalize_begin);
4741                 mono_profiler_set_gc_finalized_callback (handle, finalize_end);
4742                 mono_profiler_set_gc_finalizing_object_callback (handle, finalize_object_begin);
4743         }
4744
4745         //On Demand heapshot uses the finalizer thread to force a collection and thus a heapshot
4746         mono_profiler_set_gc_finalized_callback (handle, finalize_end);
4747
4748         if (ENABLED (PROFLOG_SAMPLE_EVENTS))
4749                 mono_profiler_set_sample_hit_callback (handle, mono_sample_hit);
4750
4751         if (ENABLED (PROFLOG_JIT_EVENTS))
4752                 mono_profiler_set_jit_code_buffer_callback (handle, code_buffer_new);
4753
4754         if (log_config.enter_leave) {
4755                 mono_profiler_set_call_instrumentation_filter_callback (handle, method_filter);
4756                 mono_profiler_set_method_enter_callback (handle, method_enter);
4757                 mono_profiler_set_method_leave_callback (handle, method_leave);
4758                 mono_profiler_set_method_tail_call_callback (handle, tail_call);
4759                 mono_profiler_set_method_exception_leave_callback (handle, method_exc_leave);
4760         }
4761
4762         if (log_config.collect_coverage) {
4763                 mono_profiler_enable_coverage ();
4764                 mono_profiler_set_coverage_filter_callback (handle, coverage_filter);
4765         }
4766
4767         mono_profiler_enable_allocations ();
4768         mono_profiler_enable_sampling (handle);
4769
4770         /*
4771          * If no sample option was given by the user, this just leaves the sampling
4772          * thread in idle mode. We do this even if no option was given so that we
4773          * can warn if another profiler controls sampling parameters.
4774          */
4775         if (!mono_profiler_set_sample_mode (handle, log_config.sampling_mode, log_config.sample_freq))
4776                 mono_profiler_printf_err ("Another profiler controls sampling parameters; the log profiler will not be able to modify them.");
4777 }