f3dbc56cbad61ad5382d149c07877bdd0359877b
[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         return MONO_PROFILER_CALL_INSTRUMENTATION_ENTER |
1820                MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE |
1821                MONO_PROFILER_CALL_INSTRUMENTATION_TAIL_CALL |
1822                MONO_PROFILER_CALL_INSTRUMENTATION_EXCEPTION_LEAVE;
1823 }
1824
1825 static void
1826 method_jitted (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *ji)
1827 {
1828         buffer_lock ();
1829
1830         register_method_local (method, ji);
1831
1832         buffer_unlock ();
1833 }
1834
1835 static void
1836 code_buffer_new (MonoProfiler *prof, const mono_byte *buffer, uint64_t size, MonoProfilerCodeBufferType type, const void *data)
1837 {
1838         const char *name;
1839         int nlen;
1840
1841         if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE) {
1842                 name = (const char *) data;
1843                 nlen = strlen (name) + 1;
1844         } else {
1845                 name = NULL;
1846                 nlen = 0;
1847         }
1848
1849         ENTER_LOG (&code_buffers_ctr, logbuffer,
1850                 EVENT_SIZE /* event */ +
1851                 BYTE_SIZE /* type */ +
1852                 LEB128_SIZE /* buffer */ +
1853                 LEB128_SIZE /* size */ +
1854                 (name ? (
1855                         nlen /* name */
1856                 ) : 0)
1857         );
1858
1859         emit_event (logbuffer, TYPE_JITHELPER | TYPE_RUNTIME);
1860         emit_byte (logbuffer, type);
1861         emit_ptr (logbuffer, buffer);
1862         emit_value (logbuffer, size);
1863
1864         if (name) {
1865                 memcpy (logbuffer->cursor, name, nlen);
1866                 logbuffer->cursor += nlen;
1867         }
1868
1869         EXIT_LOG;
1870 }
1871
1872 static void
1873 throw_exc (MonoProfiler *prof, MonoObject *object)
1874 {
1875         int do_bt = (!log_config.enter_leave && InterlockedRead (&log_profiler.runtime_inited) && log_config.num_frames) ? TYPE_THROW_BT : 0;
1876         FrameData data;
1877
1878         if (do_bt)
1879                 collect_bt (&data);
1880
1881         ENTER_LOG (&exception_throws_ctr, logbuffer,
1882                 EVENT_SIZE /* event */ +
1883                 LEB128_SIZE /* object */ +
1884                 (do_bt ? (
1885                         LEB128_SIZE /* count */ +
1886                         data.count * (
1887                                 LEB128_SIZE /* method */
1888                         )
1889                 ) : 0)
1890         );
1891
1892         emit_event (logbuffer, do_bt | TYPE_EXCEPTION);
1893         emit_obj (logbuffer, object);
1894
1895         if (do_bt)
1896                 emit_bt (logbuffer, &data);
1897
1898         EXIT_LOG;
1899 }
1900
1901 static void
1902 clause_exc (MonoProfiler *prof, MonoMethod *method, uint32_t clause_num, MonoExceptionEnum clause_type, MonoObject *exc)
1903 {
1904         ENTER_LOG (&exception_clauses_ctr, logbuffer,
1905                 EVENT_SIZE /* event */ +
1906                 BYTE_SIZE /* clause type */ +
1907                 LEB128_SIZE /* clause num */ +
1908                 LEB128_SIZE /* method */ +
1909                 LEB128_SIZE /* exc */
1910         );
1911
1912         emit_event (logbuffer, TYPE_EXCEPTION | TYPE_CLAUSE);
1913         emit_byte (logbuffer, clause_type);
1914         emit_value (logbuffer, clause_num);
1915         emit_method (logbuffer, method);
1916         emit_obj (logbuffer, exc);
1917
1918         EXIT_LOG;
1919 }
1920
1921 static void
1922 monitor_event (MonoProfiler *profiler, MonoObject *object, MonoProfilerMonitorEvent ev)
1923 {
1924         int do_bt = (!log_config.enter_leave && InterlockedRead (&log_profiler.runtime_inited) && log_config.num_frames) ? TYPE_MONITOR_BT : 0;
1925         FrameData data;
1926
1927         if (do_bt)
1928                 collect_bt (&data);
1929
1930         ENTER_LOG (&monitor_events_ctr, logbuffer,
1931                 EVENT_SIZE /* event */ +
1932                 BYTE_SIZE /* ev */ +
1933                 LEB128_SIZE /* object */ +
1934                 (do_bt ? (
1935                         LEB128_SIZE /* count */ +
1936                         data.count * (
1937                                 LEB128_SIZE /* method */
1938                         )
1939                 ) : 0)
1940         );
1941
1942         emit_event (logbuffer, do_bt | TYPE_MONITOR);
1943         emit_byte (logbuffer, ev);
1944         emit_obj (logbuffer, object);
1945
1946         if (do_bt)
1947                 emit_bt (logbuffer, &data);
1948
1949         EXIT_LOG;
1950 }
1951
1952 static void
1953 monitor_contention (MonoProfiler *prof, MonoObject *object)
1954 {
1955         monitor_event (prof, object, MONO_PROFILER_MONITOR_CONTENTION);
1956 }
1957
1958 static void
1959 monitor_acquired (MonoProfiler *prof, MonoObject *object)
1960 {
1961         monitor_event (prof, object, MONO_PROFILER_MONITOR_DONE);
1962 }
1963
1964 static void
1965 monitor_failed (MonoProfiler *prof, MonoObject *object)
1966 {
1967         monitor_event (prof, object, MONO_PROFILER_MONITOR_FAIL);
1968 }
1969
1970 static void
1971 thread_start (MonoProfiler *prof, uintptr_t tid)
1972 {
1973         ENTER_LOG (&thread_starts_ctr, logbuffer,
1974                 EVENT_SIZE /* event */ +
1975                 BYTE_SIZE /* type */ +
1976                 LEB128_SIZE /* tid */
1977         );
1978
1979         emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
1980         emit_byte (logbuffer, TYPE_THREAD);
1981         emit_ptr (logbuffer, (void*) tid);
1982
1983         EXIT_LOG;
1984 }
1985
1986 static void
1987 thread_end (MonoProfiler *prof, uintptr_t tid)
1988 {
1989         ENTER_LOG (&thread_ends_ctr, logbuffer,
1990                 EVENT_SIZE /* event */ +
1991                 BYTE_SIZE /* type */ +
1992                 LEB128_SIZE /* tid */
1993         );
1994
1995         emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
1996         emit_byte (logbuffer, TYPE_THREAD);
1997         emit_ptr (logbuffer, (void*) tid);
1998
1999         EXIT_LOG_EXPLICIT (NO_SEND);
2000
2001         MonoProfilerThread *thread = get_thread ();
2002
2003         thread->ended = TRUE;
2004         remove_thread (thread);
2005
2006         PROF_TLS_SET (NULL);
2007 }
2008
2009 static void
2010 thread_name (MonoProfiler *prof, uintptr_t tid, const char *name)
2011 {
2012         int len = strlen (name) + 1;
2013
2014         ENTER_LOG (&thread_names_ctr, logbuffer,
2015                 EVENT_SIZE /* event */ +
2016                 BYTE_SIZE /* type */ +
2017                 LEB128_SIZE /* tid */ +
2018                 len /* name */
2019         );
2020
2021         emit_event (logbuffer, TYPE_METADATA);
2022         emit_byte (logbuffer, TYPE_THREAD);
2023         emit_ptr (logbuffer, (void*)tid);
2024         memcpy (logbuffer->cursor, name, len);
2025         logbuffer->cursor += len;
2026
2027         EXIT_LOG;
2028 }
2029
2030 static void
2031 domain_loaded (MonoProfiler *prof, MonoDomain *domain)
2032 {
2033         ENTER_LOG (&domain_loads_ctr, logbuffer,
2034                 EVENT_SIZE /* event */ +
2035                 BYTE_SIZE /* type */ +
2036                 LEB128_SIZE /* domain id */
2037         );
2038
2039         emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
2040         emit_byte (logbuffer, TYPE_DOMAIN);
2041         emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
2042
2043         EXIT_LOG;
2044 }
2045
2046 static void
2047 domain_unloaded (MonoProfiler *prof, MonoDomain *domain)
2048 {
2049         ENTER_LOG (&domain_unloads_ctr, logbuffer,
2050                 EVENT_SIZE /* event */ +
2051                 BYTE_SIZE /* type */ +
2052                 LEB128_SIZE /* domain id */
2053         );
2054
2055         emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
2056         emit_byte (logbuffer, TYPE_DOMAIN);
2057         emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
2058
2059         EXIT_LOG;
2060 }
2061
2062 static void
2063 domain_name (MonoProfiler *prof, MonoDomain *domain, const char *name)
2064 {
2065         int nlen = strlen (name) + 1;
2066
2067         ENTER_LOG (&domain_names_ctr, logbuffer,
2068                 EVENT_SIZE /* event */ +
2069                 BYTE_SIZE /* type */ +
2070                 LEB128_SIZE /* domain id */ +
2071                 nlen /* name */
2072         );
2073
2074         emit_event (logbuffer, TYPE_METADATA);
2075         emit_byte (logbuffer, TYPE_DOMAIN);
2076         emit_ptr (logbuffer, (void*)(uintptr_t) mono_domain_get_id (domain));
2077         memcpy (logbuffer->cursor, name, nlen);
2078         logbuffer->cursor += nlen;
2079
2080         EXIT_LOG;
2081 }
2082
2083 static void
2084 context_loaded (MonoProfiler *prof, MonoAppContext *context)
2085 {
2086         ENTER_LOG (&context_loads_ctr, logbuffer,
2087                 EVENT_SIZE /* event */ +
2088                 BYTE_SIZE /* type */ +
2089                 LEB128_SIZE /* context id */ +
2090                 LEB128_SIZE /* domain id */
2091         );
2092
2093         emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
2094         emit_byte (logbuffer, TYPE_CONTEXT);
2095         emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_id (context));
2096         emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_domain_id (context));
2097
2098         EXIT_LOG;
2099 }
2100
2101 static void
2102 context_unloaded (MonoProfiler *prof, MonoAppContext *context)
2103 {
2104         ENTER_LOG (&context_unloads_ctr, logbuffer,
2105                 EVENT_SIZE /* event */ +
2106                 BYTE_SIZE /* type */ +
2107                 LEB128_SIZE /* context id */ +
2108                 LEB128_SIZE /* domain id */
2109         );
2110
2111         emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
2112         emit_byte (logbuffer, TYPE_CONTEXT);
2113         emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_id (context));
2114         emit_ptr (logbuffer, (void*)(uintptr_t) mono_context_get_domain_id (context));
2115
2116         EXIT_LOG;
2117 }
2118
2119 typedef struct {
2120         MonoMethod *method;
2121         MonoDomain *domain;
2122         void *base_address;
2123         int offset;
2124 } AsyncFrameInfo;
2125
2126 typedef struct {
2127         MonoLockFreeQueueNode node;
2128         uint64_t time;
2129         uintptr_t tid;
2130         const void *ip;
2131         int count;
2132         AsyncFrameInfo frames [MONO_ZERO_LEN_ARRAY];
2133 } SampleHit;
2134
2135 static mono_bool
2136 async_walk_stack (MonoMethod *method, MonoDomain *domain, void *base_address, int offset, void *data)
2137 {
2138         SampleHit *sample = (SampleHit *) data;
2139
2140         if (sample->count < log_config.num_frames) {
2141                 int i = sample->count;
2142
2143                 sample->frames [i].method = method;
2144                 sample->frames [i].domain = domain;
2145                 sample->frames [i].base_address = base_address;
2146                 sample->frames [i].offset = offset;
2147
2148                 sample->count++;
2149         }
2150
2151         return sample->count == log_config.num_frames;
2152 }
2153
2154 #define SAMPLE_SLOT_SIZE(FRAMES) (sizeof (SampleHit) + sizeof (AsyncFrameInfo) * (FRAMES - MONO_ZERO_LEN_ARRAY))
2155 #define SAMPLE_BLOCK_SIZE (mono_pagesize ())
2156
2157 static void
2158 enqueue_sample_hit (gpointer p)
2159 {
2160         SampleHit *sample = p;
2161
2162         mono_lock_free_queue_node_unpoison (&sample->node);
2163         mono_lock_free_queue_enqueue (&log_profiler.dumper_queue, &sample->node);
2164         mono_os_sem_post (&log_profiler.dumper_queue_sem);
2165 }
2166
2167 static void
2168 mono_sample_hit (MonoProfiler *profiler, const mono_byte *ip, const void *context)
2169 {
2170         /*
2171          * Please note: We rely on the runtime loading the profiler with
2172          * MONO_DL_EAGER (RTLD_NOW) so that references to runtime functions within
2173          * this function (and its siblings) are resolved when the profiler is
2174          * loaded. Otherwise, we would potentially invoke the dynamic linker when
2175          * invoking runtime functions, which is not async-signal-safe.
2176          */
2177
2178         if (InterlockedRead (&log_profiler.in_shutdown))
2179                 return;
2180
2181         SampleHit *sample = (SampleHit *) mono_lock_free_queue_dequeue (&profiler->sample_reuse_queue);
2182
2183         if (!sample) {
2184                 /*
2185                  * If we're out of reusable sample events and we're not allowed to
2186                  * allocate more, we have no choice but to drop the event.
2187                  */
2188                 if (InterlockedRead (&sample_allocations_ctr) >= log_config.max_allocated_sample_hits)
2189                         return;
2190
2191                 sample = mono_lock_free_alloc (&profiler->sample_allocator);
2192                 mono_lock_free_queue_node_init (&sample->node, TRUE);
2193
2194                 InterlockedIncrement (&sample_allocations_ctr);
2195         }
2196
2197         sample->count = 0;
2198         mono_stack_walk_async_safe (&async_walk_stack, (void *) context, sample);
2199
2200         sample->time = current_time ();
2201         sample->tid = thread_id ();
2202         sample->ip = ip;
2203
2204         mono_thread_hazardous_try_free (sample, enqueue_sample_hit);
2205 }
2206
2207 static uintptr_t *code_pages = 0;
2208 static int num_code_pages = 0;
2209 static int size_code_pages = 0;
2210 #define CPAGE_SHIFT (9)
2211 #define CPAGE_SIZE (1 << CPAGE_SHIFT)
2212 #define CPAGE_MASK (~(CPAGE_SIZE - 1))
2213 #define CPAGE_ADDR(p) ((p) & CPAGE_MASK)
2214
2215 static uintptr_t
2216 add_code_page (uintptr_t *hash, uintptr_t hsize, uintptr_t page)
2217 {
2218         uintptr_t i;
2219         uintptr_t start_pos;
2220         start_pos = (page >> CPAGE_SHIFT) % hsize;
2221         i = start_pos;
2222         do {
2223                 if (hash [i] && CPAGE_ADDR (hash [i]) == CPAGE_ADDR (page)) {
2224                         return 0;
2225                 } else if (!hash [i]) {
2226                         hash [i] = page;
2227                         return 1;
2228                 }
2229                 /* wrap around */
2230                 if (++i == hsize)
2231                         i = 0;
2232         } while (i != start_pos);
2233         g_assert_not_reached ();
2234         return 0;
2235 }
2236
2237 static void
2238 add_code_pointer (uintptr_t ip)
2239 {
2240         uintptr_t i;
2241         if (num_code_pages * 2 >= size_code_pages) {
2242                 uintptr_t *n;
2243                 uintptr_t old_size = size_code_pages;
2244                 size_code_pages *= 2;
2245                 if (size_code_pages == 0)
2246                         size_code_pages = 16;
2247                 n = (uintptr_t *) g_calloc (sizeof (uintptr_t) * size_code_pages, 1);
2248                 for (i = 0; i < old_size; ++i) {
2249                         if (code_pages [i])
2250                                 add_code_page (n, size_code_pages, code_pages [i]);
2251                 }
2252                 if (code_pages)
2253                         g_free (code_pages);
2254                 code_pages = n;
2255         }
2256         num_code_pages += add_code_page (code_pages, size_code_pages, ip & CPAGE_MASK);
2257 }
2258
2259 /* ELF code crashes on some systems. */
2260 //#if defined(HAVE_DL_ITERATE_PHDR) && defined(ELFMAG0)
2261 #if 0
2262 static void
2263 dump_ubin (const char *filename, uintptr_t load_addr, uint64_t offset, uintptr_t size)
2264 {
2265         int len = strlen (filename) + 1;
2266
2267         ENTER_LOG (&sample_ubins_ctr, logbuffer,
2268                 EVENT_SIZE /* event */ +
2269                 LEB128_SIZE /* load address */ +
2270                 LEB128_SIZE /* offset */ +
2271                 LEB128_SIZE /* size */ +
2272                 len /* file name */
2273         );
2274
2275         emit_event (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_UBIN);
2276         emit_ptr (logbuffer, load_addr);
2277         emit_uvalue (logbuffer, offset);
2278         emit_uvalue (logbuffer, size);
2279         memcpy (logbuffer->cursor, filename, len);
2280         logbuffer->cursor += len;
2281
2282         EXIT_LOG;
2283 }
2284 #endif
2285
2286 static void
2287 dump_usym (const char *name, uintptr_t value, uintptr_t size)
2288 {
2289         int len = strlen (name) + 1;
2290
2291         ENTER_LOG (&sample_usyms_ctr, logbuffer,
2292                 EVENT_SIZE /* event */ +
2293                 LEB128_SIZE /* value */ +
2294                 LEB128_SIZE /* size */ +
2295                 len /* name */
2296         );
2297
2298         emit_event (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_USYM);
2299         emit_ptr (logbuffer, (void*)value);
2300         emit_value (logbuffer, size);
2301         memcpy (logbuffer->cursor, name, len);
2302         logbuffer->cursor += len;
2303
2304         EXIT_LOG;
2305 }
2306
2307 /* ELF code crashes on some systems. */
2308 //#if defined(ELFMAG0)
2309 #if 0
2310
2311 #if SIZEOF_VOID_P == 4
2312 #define ELF_WSIZE 32
2313 #else
2314 #define ELF_WSIZE 64
2315 #endif
2316 #ifndef ElfW
2317 #define ElfW(type)      _ElfW (Elf, ELF_WSIZE, type)
2318 #define _ElfW(e,w,t)    _ElfW_1 (e, w, _##t)
2319 #define _ElfW_1(e,w,t)  e##w##t
2320 #endif
2321
2322 static void
2323 dump_elf_symbols (ElfW(Sym) *symbols, int num_symbols, const char *strtab, void *load_addr)
2324 {
2325         int i;
2326         for (i = 0; i < num_symbols; ++i) {
2327                 const char* sym;
2328                 sym =  strtab + symbols [i].st_name;
2329                 if (!symbols [i].st_name || !symbols [i].st_size || (symbols [i].st_info & 0xf) != STT_FUNC)
2330                         continue;
2331                 dump_usym (sym, (uintptr_t)load_addr + symbols [i].st_value, symbols [i].st_size);
2332         }
2333 }
2334
2335 static int
2336 read_elf_symbols (MonoProfiler *prof, const char *filename, void *load_addr)
2337 {
2338         int fd, i;
2339         void *data;
2340         struct stat statb;
2341         uint64_t file_size;
2342         ElfW(Ehdr) *header;
2343         ElfW(Shdr) *sheader;
2344         ElfW(Shdr) *shstrtabh;
2345         ElfW(Shdr) *symtabh = NULL;
2346         ElfW(Shdr) *strtabh = NULL;
2347         ElfW(Sym) *symbols = NULL;
2348         const char *strtab;
2349         int num_symbols;
2350
2351         fd = open (filename, O_RDONLY);
2352         if (fd < 0)
2353                 return 0;
2354         if (fstat (fd, &statb) != 0) {
2355                 close (fd);
2356                 return 0;
2357         }
2358         file_size = statb.st_size;
2359         data = mmap (NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
2360         close (fd);
2361         if (data == MAP_FAILED)
2362                 return 0;
2363         header = data;
2364         if (header->e_ident [EI_MAG0] != ELFMAG0 ||
2365                         header->e_ident [EI_MAG1] != ELFMAG1 ||
2366                         header->e_ident [EI_MAG2] != ELFMAG2 ||
2367                         header->e_ident [EI_MAG3] != ELFMAG3 ) {
2368                 munmap (data, file_size);
2369                 return 0;
2370         }
2371         sheader = (void*)((char*)data + header->e_shoff);
2372         shstrtabh = (void*)((char*)sheader + (header->e_shentsize * header->e_shstrndx));
2373         strtab = (const char*)data + shstrtabh->sh_offset;
2374         for (i = 0; i < header->e_shnum; ++i) {
2375                 if (sheader->sh_type == SHT_SYMTAB) {
2376                         symtabh = sheader;
2377                         strtabh = (void*)((char*)data + header->e_shoff + sheader->sh_link * header->e_shentsize);
2378                         break;
2379                 }
2380                 sheader = (void*)((char*)sheader + header->e_shentsize);
2381         }
2382         if (!symtabh || !strtabh) {
2383                 munmap (data, file_size);
2384                 return 0;
2385         }
2386         strtab = (const char*)data + strtabh->sh_offset;
2387         num_symbols = symtabh->sh_size / symtabh->sh_entsize;
2388         symbols = (void*)((char*)data + symtabh->sh_offset);
2389         dump_elf_symbols (symbols, num_symbols, strtab, load_addr);
2390         munmap (data, file_size);
2391         return 1;
2392 }
2393 #endif
2394
2395 /* ELF code crashes on some systems. */
2396 //#if defined(HAVE_DL_ITERATE_PHDR) && defined(ELFMAG0)
2397 #if 0
2398 static int
2399 elf_dl_callback (struct dl_phdr_info *info, size_t size, void *data)
2400 {
2401         char buf [256];
2402         const char *filename;
2403         BinaryObject *obj;
2404         char *a = (void*)info->dlpi_addr;
2405         int i, num_sym;
2406         ElfW(Dyn) *dyn = NULL;
2407         ElfW(Sym) *symtab = NULL;
2408         ElfW(Word) *hash_table = NULL;
2409         ElfW(Ehdr) *header = NULL;
2410         const char* strtab = NULL;
2411         for (obj = log_profiler.binary_objects; obj; obj = obj->next) {
2412                 if (obj->addr == a)
2413                         return 0;
2414         }
2415         filename = info->dlpi_name;
2416         if (!filename)
2417                 return 0;
2418         if (!info->dlpi_addr && !filename [0]) {
2419                 int l = readlink ("/proc/self/exe", buf, sizeof (buf) - 1);
2420                 if (l > 0) {
2421                         buf [l] = 0;
2422                         filename = buf;
2423                 }
2424         }
2425         obj = g_calloc (sizeof (BinaryObject), 1);
2426         obj->addr = (void*)info->dlpi_addr;
2427         obj->name = pstrdup (filename);
2428         obj->next = log_profiler.binary_objects;
2429         log_profiler.binary_objects = obj;
2430         a = NULL;
2431         for (i = 0; i < info->dlpi_phnum; ++i) {
2432                 if (info->dlpi_phdr[i].p_type == PT_LOAD && !header) {
2433                         header = (ElfW(Ehdr)*)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
2434                         if (header->e_ident [EI_MAG0] != ELFMAG0 ||
2435                                         header->e_ident [EI_MAG1] != ELFMAG1 ||
2436                                         header->e_ident [EI_MAG2] != ELFMAG2 ||
2437                                         header->e_ident [EI_MAG3] != ELFMAG3 ) {
2438                                 header = NULL;
2439                         }
2440                         dump_ubin (filename, info->dlpi_addr + info->dlpi_phdr[i].p_vaddr, info->dlpi_phdr[i].p_offset, info->dlpi_phdr[i].p_memsz);
2441                 } else if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) {
2442                         dyn = (ElfW(Dyn) *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
2443                 }
2444         }
2445         if (read_elf_symbols (filename, (void*)info->dlpi_addr))
2446                 return 0;
2447         if (!info->dlpi_name || !info->dlpi_name[0])
2448                 return 0;
2449         if (!dyn)
2450                 return 0;
2451         for (i = 0; dyn [i].d_tag != DT_NULL; ++i) {
2452                 if (dyn [i].d_tag == DT_SYMTAB) {
2453                         symtab = (ElfW(Sym) *)(a + dyn [i].d_un.d_ptr);
2454                 } else if (dyn [i].d_tag == DT_HASH) {
2455                         hash_table = (ElfW(Word) *)(a + dyn [i].d_un.d_ptr);
2456                 } else if (dyn [i].d_tag == DT_STRTAB) {
2457                         strtab = (const char*)(a + dyn [i].d_un.d_ptr);
2458                 }
2459         }
2460         if (!hash_table)
2461                 return 0;
2462         num_sym = hash_table [1];
2463         dump_elf_symbols (symtab, num_sym, strtab, (void*)info->dlpi_addr);
2464         return 0;
2465 }
2466
2467 static int
2468 load_binaries (void)
2469 {
2470         dl_iterate_phdr (elf_dl_callback, NULL);
2471         return 1;
2472 }
2473 #else
2474 static int
2475 load_binaries (void)
2476 {
2477         return 0;
2478 }
2479 #endif
2480
2481 static const char*
2482 symbol_for (uintptr_t code)
2483 {
2484 #ifdef HAVE_DLADDR
2485         void *ip = (void*)code;
2486         Dl_info di;
2487         if (dladdr (ip, &di)) {
2488                 if (di.dli_sname)
2489                         return di.dli_sname;
2490         } else {
2491         /*      char **names;
2492                 names = backtrace_symbols (&ip, 1);
2493                 if (names) {
2494                         const char* p = names [0];
2495                         g_free (names);
2496                         return p;
2497                 }
2498                 */
2499         }
2500 #endif
2501         return NULL;
2502 }
2503
2504 static void
2505 dump_unmanaged_coderefs (void)
2506 {
2507         int i;
2508         const char* last_symbol;
2509         uintptr_t addr, page_end;
2510
2511         if (load_binaries ())
2512                 return;
2513         for (i = 0; i < size_code_pages; ++i) {
2514                 const char* sym;
2515                 if (!code_pages [i] || code_pages [i] & 1)
2516                         continue;
2517                 last_symbol = NULL;
2518                 addr = CPAGE_ADDR (code_pages [i]);
2519                 page_end = addr + CPAGE_SIZE;
2520                 code_pages [i] |= 1;
2521                 /* we dump the symbols for the whole page */
2522                 for (; addr < page_end; addr += 16) {
2523                         sym = symbol_for (addr);
2524                         if (sym && sym == last_symbol)
2525                                 continue;
2526                         last_symbol = sym;
2527                         if (!sym)
2528                                 continue;
2529                         dump_usym (sym, addr, 0); /* let's not guess the size */
2530                 }
2531         }
2532 }
2533
2534 static void
2535 counters_add_agent (MonoCounter *counter)
2536 {
2537         if (InterlockedRead (&log_profiler.in_shutdown))
2538                 return;
2539
2540         MonoCounterAgent *agent, *item;
2541
2542         mono_os_mutex_lock (&log_profiler.counters_mutex);
2543
2544         for (agent = log_profiler.counters; agent; agent = agent->next) {
2545                 if (agent->counter == counter) {
2546                         agent->value_size = 0;
2547                         if (agent->value) {
2548                                 g_free (agent->value);
2549                                 agent->value = NULL;
2550                         }
2551                         goto done;
2552                 }
2553         }
2554
2555         agent = (MonoCounterAgent *) g_malloc (sizeof (MonoCounterAgent));
2556         agent->counter = counter;
2557         agent->value = NULL;
2558         agent->value_size = 0;
2559         agent->index = log_profiler.counters_index++;
2560         agent->emitted = FALSE;
2561         agent->next = NULL;
2562
2563         if (!log_profiler.counters) {
2564                 log_profiler.counters = agent;
2565         } else {
2566                 item = log_profiler.counters;
2567                 while (item->next)
2568                         item = item->next;
2569                 item->next = agent;
2570         }
2571
2572 done:
2573         mono_os_mutex_unlock (&log_profiler.counters_mutex);
2574 }
2575
2576 static mono_bool
2577 counters_init_foreach_callback (MonoCounter *counter, gpointer data)
2578 {
2579         counters_add_agent (counter);
2580         return TRUE;
2581 }
2582
2583 static void
2584 counters_init (void)
2585 {
2586         mono_os_mutex_init (&log_profiler.counters_mutex);
2587
2588         log_profiler.counters_index = 1;
2589
2590         mono_counters_on_register (&counters_add_agent);
2591         mono_counters_foreach (counters_init_foreach_callback, NULL);
2592 }
2593
2594 static void
2595 counters_emit (void)
2596 {
2597         MonoCounterAgent *agent;
2598         int len = 0;
2599         int size =
2600                 EVENT_SIZE /* event */ +
2601                 LEB128_SIZE /* len */
2602         ;
2603
2604         mono_os_mutex_lock (&log_profiler.counters_mutex);
2605
2606         for (agent = log_profiler.counters; agent; agent = agent->next) {
2607                 if (agent->emitted)
2608                         continue;
2609
2610                 size +=
2611                         LEB128_SIZE /* section */ +
2612                         strlen (mono_counter_get_name (agent->counter)) + 1 /* name */ +
2613                         BYTE_SIZE /* type */ +
2614                         BYTE_SIZE /* unit */ +
2615                         BYTE_SIZE /* variance */ +
2616                         LEB128_SIZE /* index */
2617                 ;
2618
2619                 len++;
2620         }
2621
2622         if (!len)
2623                 goto done;
2624
2625         ENTER_LOG (&counter_descriptors_ctr, logbuffer, size);
2626
2627         emit_event (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
2628         emit_value (logbuffer, len);
2629
2630         for (agent = log_profiler.counters; agent; agent = agent->next) {
2631                 const char *name;
2632
2633                 if (agent->emitted)
2634                         continue;
2635
2636                 name = mono_counter_get_name (agent->counter);
2637                 emit_value (logbuffer, mono_counter_get_section (agent->counter));
2638                 emit_string (logbuffer, name, strlen (name) + 1);
2639                 emit_byte (logbuffer, mono_counter_get_type (agent->counter));
2640                 emit_byte (logbuffer, mono_counter_get_unit (agent->counter));
2641                 emit_byte (logbuffer, mono_counter_get_variance (agent->counter));
2642                 emit_value (logbuffer, agent->index);
2643
2644                 agent->emitted = TRUE;
2645         }
2646
2647         EXIT_LOG;
2648
2649 done:
2650         mono_os_mutex_unlock (&log_profiler.counters_mutex);
2651 }
2652
2653 static void
2654 counters_sample (uint64_t timestamp)
2655 {
2656         MonoCounterAgent *agent;
2657         MonoCounter *counter;
2658         int type;
2659         int buffer_size;
2660         void *buffer;
2661         int size;
2662
2663         counters_emit ();
2664
2665         buffer_size = 8;
2666         buffer = g_calloc (1, buffer_size);
2667
2668         mono_os_mutex_lock (&log_profiler.counters_mutex);
2669
2670         size =
2671                 EVENT_SIZE /* event */
2672         ;
2673
2674         for (agent = log_profiler.counters; agent; agent = agent->next) {
2675                 /*
2676                  * FIXME: This calculation is incorrect for string counters since
2677                  * mono_counter_get_size () just returns 0 in that case. We should
2678                  * address this if we ever actually add any string counters to Mono.
2679                  */
2680
2681                 size +=
2682                         LEB128_SIZE /* index */ +
2683                         BYTE_SIZE /* type */ +
2684                         mono_counter_get_size (agent->counter) /* value */
2685                 ;
2686         }
2687
2688         size +=
2689                 LEB128_SIZE /* stop marker */
2690         ;
2691
2692         ENTER_LOG (&counter_samples_ctr, logbuffer, size);
2693
2694         emit_event_time (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE, timestamp);
2695
2696         for (agent = log_profiler.counters; agent; agent = agent->next) {
2697                 size_t size;
2698
2699                 counter = agent->counter;
2700
2701                 size = mono_counter_get_size (counter);
2702
2703                 if (size > buffer_size) {
2704                         buffer_size = size;
2705                         buffer = g_realloc (buffer, buffer_size);
2706                 }
2707
2708                 memset (buffer, 0, buffer_size);
2709
2710                 g_assert (mono_counters_sample (counter, buffer, size));
2711
2712                 type = mono_counter_get_type (counter);
2713
2714                 if (!agent->value) {
2715                         agent->value = g_calloc (1, size);
2716                         agent->value_size = size;
2717                 } else {
2718                         if (type == MONO_COUNTER_STRING) {
2719                                 if (strcmp (agent->value, buffer) == 0)
2720                                         continue;
2721                         } else {
2722                                 if (agent->value_size == size && memcmp (agent->value, buffer, size) == 0)
2723                                         continue;
2724                         }
2725                 }
2726
2727                 emit_uvalue (logbuffer, agent->index);
2728                 emit_byte (logbuffer, type);
2729                 switch (type) {
2730                 case MONO_COUNTER_INT:
2731 #if SIZEOF_VOID_P == 4
2732                 case MONO_COUNTER_WORD:
2733 #endif
2734                         emit_svalue (logbuffer, *(int*)buffer - *(int*)agent->value);
2735                         break;
2736                 case MONO_COUNTER_UINT:
2737                         emit_uvalue (logbuffer, *(guint*)buffer - *(guint*)agent->value);
2738                         break;
2739                 case MONO_COUNTER_TIME_INTERVAL:
2740                 case MONO_COUNTER_LONG:
2741 #if SIZEOF_VOID_P == 8
2742                 case MONO_COUNTER_WORD:
2743 #endif
2744                         emit_svalue (logbuffer, *(gint64*)buffer - *(gint64*)agent->value);
2745                         break;
2746                 case MONO_COUNTER_ULONG:
2747                         emit_uvalue (logbuffer, *(guint64*)buffer - *(guint64*)agent->value);
2748                         break;
2749                 case MONO_COUNTER_DOUBLE:
2750                         emit_double (logbuffer, *(double*)buffer);
2751                         break;
2752                 case MONO_COUNTER_STRING:
2753                         if (size == 0) {
2754                                 emit_byte (logbuffer, 0);
2755                         } else {
2756                                 emit_byte (logbuffer, 1);
2757                                 emit_string (logbuffer, (char*)buffer, size);
2758                         }
2759                         break;
2760                 default:
2761                         g_assert_not_reached ();
2762                 }
2763
2764                 if (type == MONO_COUNTER_STRING && size > agent->value_size) {
2765                         agent->value = g_realloc (agent->value, size);
2766                         agent->value_size = size;
2767                 }
2768
2769                 if (size > 0)
2770                         memcpy (agent->value, buffer, size);
2771         }
2772         g_free (buffer);
2773
2774         emit_value (logbuffer, 0);
2775
2776         EXIT_LOG;
2777
2778         mono_os_mutex_unlock (&log_profiler.counters_mutex);
2779 }
2780
2781 static void
2782 perfcounters_emit (void)
2783 {
2784         PerfCounterAgent *pcagent;
2785         int len = 0;
2786         int size =
2787                 EVENT_SIZE /* event */ +
2788                 LEB128_SIZE /* len */
2789         ;
2790
2791         for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
2792                 if (pcagent->emitted)
2793                         continue;
2794
2795                 size +=
2796                         LEB128_SIZE /* section */ +
2797                         strlen (pcagent->category_name) + 1 /* category name */ +
2798                         strlen (pcagent->name) + 1 /* name */ +
2799                         BYTE_SIZE /* type */ +
2800                         BYTE_SIZE /* unit */ +
2801                         BYTE_SIZE /* variance */ +
2802                         LEB128_SIZE /* index */
2803                 ;
2804
2805                 len++;
2806         }
2807
2808         if (!len)
2809                 return;
2810
2811         ENTER_LOG (&perfcounter_descriptors_ctr, logbuffer, size);
2812
2813         emit_event (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
2814         emit_value (logbuffer, len);
2815
2816         for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
2817                 if (pcagent->emitted)
2818                         continue;
2819
2820                 emit_value (logbuffer, MONO_COUNTER_PERFCOUNTERS);
2821                 emit_string (logbuffer, pcagent->category_name, strlen (pcagent->category_name) + 1);
2822                 emit_string (logbuffer, pcagent->name, strlen (pcagent->name) + 1);
2823                 emit_byte (logbuffer, MONO_COUNTER_LONG);
2824                 emit_byte (logbuffer, MONO_COUNTER_RAW);
2825                 emit_byte (logbuffer, MONO_COUNTER_VARIABLE);
2826                 emit_value (logbuffer, pcagent->index);
2827
2828                 pcagent->emitted = TRUE;
2829         }
2830
2831         EXIT_LOG;
2832 }
2833
2834 static gboolean
2835 perfcounters_foreach (char *category_name, char *name, unsigned char type, gint64 value, gpointer user_data)
2836 {
2837         PerfCounterAgent *pcagent;
2838
2839         for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
2840                 if (strcmp (pcagent->category_name, category_name) != 0 || strcmp (pcagent->name, name) != 0)
2841                         continue;
2842                 if (pcagent->value == value)
2843                         return TRUE;
2844
2845                 pcagent->value = value;
2846                 pcagent->updated = TRUE;
2847                 pcagent->deleted = FALSE;
2848                 return TRUE;
2849         }
2850
2851         pcagent = g_new0 (PerfCounterAgent, 1);
2852         pcagent->next = log_profiler.perfcounters;
2853         pcagent->index = log_profiler.counters_index++;
2854         pcagent->category_name = g_strdup (category_name);
2855         pcagent->name = g_strdup (name);
2856         pcagent->value = value;
2857         pcagent->emitted = FALSE;
2858         pcagent->updated = TRUE;
2859         pcagent->deleted = FALSE;
2860
2861         log_profiler.perfcounters = pcagent;
2862
2863         return TRUE;
2864 }
2865
2866 static void
2867 perfcounters_sample (uint64_t timestamp)
2868 {
2869         PerfCounterAgent *pcagent;
2870         int len = 0;
2871         int size;
2872
2873         mono_os_mutex_lock (&log_profiler.counters_mutex);
2874
2875         /* mark all perfcounters as deleted, foreach will unmark them as necessary */
2876         for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next)
2877                 pcagent->deleted = TRUE;
2878
2879         mono_perfcounter_foreach (perfcounters_foreach, NULL);
2880
2881         perfcounters_emit ();
2882
2883         size =
2884                 EVENT_SIZE /* event */
2885         ;
2886
2887         for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
2888                 if (pcagent->deleted || !pcagent->updated)
2889                         continue;
2890
2891                 size +=
2892                         LEB128_SIZE /* index */ +
2893                         BYTE_SIZE /* type */ +
2894                         LEB128_SIZE /* value */
2895                 ;
2896
2897                 len++;
2898         }
2899
2900         if (!len)
2901                 goto done;
2902
2903         size +=
2904                 LEB128_SIZE /* stop marker */
2905         ;
2906
2907         ENTER_LOG (&perfcounter_samples_ctr, logbuffer, size);
2908
2909         emit_event_time (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE, timestamp);
2910
2911         for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
2912                 if (pcagent->deleted || !pcagent->updated)
2913                         continue;
2914                 emit_uvalue (logbuffer, pcagent->index);
2915                 emit_byte (logbuffer, MONO_COUNTER_LONG);
2916                 emit_svalue (logbuffer, pcagent->value);
2917
2918                 pcagent->updated = FALSE;
2919         }
2920
2921         emit_value (logbuffer, 0);
2922
2923         EXIT_LOG;
2924
2925 done:
2926         mono_os_mutex_unlock (&log_profiler.counters_mutex);
2927 }
2928
2929 static void
2930 counters_and_perfcounters_sample (void)
2931 {
2932         uint64_t now = current_time ();
2933
2934         counters_sample (now);
2935         perfcounters_sample (now);
2936 }
2937
2938 typedef struct {
2939         MonoLockFreeQueueNode node;
2940         MonoMethod *method;
2941 } MethodNode;
2942
2943 typedef struct {
2944         int offset;
2945         int counter;
2946         char *filename;
2947         int line;
2948         int column;
2949 } CoverageEntry;
2950
2951 static void
2952 free_coverage_entry (gpointer data, gpointer userdata)
2953 {
2954         CoverageEntry *entry = (CoverageEntry *)data;
2955         g_free (entry->filename);
2956         g_free (entry);
2957 }
2958
2959 static void
2960 obtain_coverage_for_method (MonoProfiler *prof, const MonoProfilerCoverageData *entry)
2961 {
2962         int offset = entry->il_offset - log_profiler.coverage_previous_offset;
2963         CoverageEntry *e = g_new (CoverageEntry, 1);
2964
2965         log_profiler.coverage_previous_offset = entry->il_offset;
2966
2967         e->offset = offset;
2968         e->counter = entry->counter;
2969         e->filename = g_strdup(entry->file_name ? entry->file_name : "");
2970         e->line = entry->line;
2971         e->column = entry->column;
2972
2973         g_ptr_array_add (log_profiler.coverage_data, e);
2974 }
2975
2976 static char *
2977 parse_generic_type_names(char *name)
2978 {
2979         char *new_name, *ret;
2980         int within_generic_declaration = 0, generic_members = 1;
2981
2982         if (name == NULL || *name == '\0')
2983                 return g_strdup ("");
2984
2985         if (!(ret = new_name = (char *) g_calloc (strlen (name) * 4 + 1, sizeof (char))))
2986                 return NULL;
2987
2988         do {
2989                 switch (*name) {
2990                         case '<':
2991                                 within_generic_declaration = 1;
2992                                 break;
2993
2994                         case '>':
2995                                 within_generic_declaration = 0;
2996
2997                                 if (*(name - 1) != '<') {
2998                                         *new_name++ = '`';
2999                                         *new_name++ = '0' + generic_members;
3000                                 } else {
3001                                         memcpy (new_name, "&lt;&gt;", 8);
3002                                         new_name += 8;
3003                                 }
3004
3005                                 generic_members = 0;
3006                                 break;
3007
3008                         case ',':
3009                                 generic_members++;
3010                                 break;
3011
3012                         default:
3013                                 if (!within_generic_declaration)
3014                                         *new_name++ = *name;
3015
3016                                 break;
3017                 }
3018         } while (*name++);
3019
3020         return ret;
3021 }
3022
3023 static void
3024 build_method_buffer (gpointer key, gpointer value, gpointer userdata)
3025 {
3026         MonoMethod *method = (MonoMethod *)value;
3027         MonoClass *klass;
3028         MonoImage *image;
3029         char *class_name;
3030         const char *image_name, *method_name, *sig, *first_filename;
3031         guint i;
3032
3033         log_profiler.coverage_previous_offset = 0;
3034         log_profiler.coverage_data = g_ptr_array_new ();
3035
3036         mono_profiler_get_coverage_data (log_profiler.handle, method, obtain_coverage_for_method);
3037
3038         klass = mono_method_get_class (method);
3039         image = mono_class_get_image (klass);
3040         image_name = mono_image_get_name (image);
3041
3042         sig = mono_signature_get_desc (mono_method_signature (method), TRUE);
3043         class_name = parse_generic_type_names (mono_type_get_name (mono_class_get_type (klass)));
3044         method_name = mono_method_get_name (method);
3045
3046         if (log_profiler.coverage_data->len != 0) {
3047                 CoverageEntry *entry = (CoverageEntry *)log_profiler.coverage_data->pdata[0];
3048                 first_filename = entry->filename ? entry->filename : "";
3049         } else
3050                 first_filename = "";
3051
3052         image_name = image_name ? image_name : "";
3053         sig = sig ? sig : "";
3054         method_name = method_name ? method_name : "";
3055
3056         ENTER_LOG (&coverage_methods_ctr, logbuffer,
3057                 EVENT_SIZE /* event */ +
3058                 strlen (image_name) + 1 /* image name */ +
3059                 strlen (class_name) + 1 /* class name */ +
3060                 strlen (method_name) + 1 /* method name */ +
3061                 strlen (sig) + 1 /* signature */ +
3062                 strlen (first_filename) + 1 /* first file name */ +
3063                 LEB128_SIZE /* token */ +
3064                 LEB128_SIZE /* method id */ +
3065                 LEB128_SIZE /* entries */
3066         );
3067
3068         emit_event (logbuffer, TYPE_COVERAGE_METHOD | TYPE_COVERAGE);
3069         emit_string (logbuffer, image_name, strlen (image_name) + 1);
3070         emit_string (logbuffer, class_name, strlen (class_name) + 1);
3071         emit_string (logbuffer, method_name, strlen (method_name) + 1);
3072         emit_string (logbuffer, sig, strlen (sig) + 1);
3073         emit_string (logbuffer, first_filename, strlen (first_filename) + 1);
3074
3075         emit_uvalue (logbuffer, mono_method_get_token (method));
3076         emit_uvalue (logbuffer, log_profiler.coverage_method_id);
3077         emit_value (logbuffer, log_profiler.coverage_data->len);
3078
3079         EXIT_LOG;
3080
3081         for (i = 0; i < log_profiler.coverage_data->len; i++) {
3082                 CoverageEntry *entry = (CoverageEntry *)log_profiler.coverage_data->pdata[i];
3083
3084                 ENTER_LOG (&coverage_statements_ctr, logbuffer,
3085                         EVENT_SIZE /* event */ +
3086                         LEB128_SIZE /* method id */ +
3087                         LEB128_SIZE /* offset */ +
3088                         LEB128_SIZE /* counter */ +
3089                         LEB128_SIZE /* line */ +
3090                         LEB128_SIZE /* column */
3091                 );
3092
3093                 emit_event (logbuffer, TYPE_COVERAGE_STATEMENT | TYPE_COVERAGE);
3094                 emit_uvalue (logbuffer, log_profiler.coverage_method_id);
3095                 emit_uvalue (logbuffer, entry->offset);
3096                 emit_uvalue (logbuffer, entry->counter);
3097                 emit_uvalue (logbuffer, entry->line);
3098                 emit_uvalue (logbuffer, entry->column);
3099
3100                 EXIT_LOG;
3101         }
3102
3103         log_profiler.coverage_method_id++;
3104
3105         g_free (class_name);
3106
3107         g_ptr_array_foreach (log_profiler.coverage_data, free_coverage_entry, NULL);
3108         g_ptr_array_free (log_profiler.coverage_data, TRUE);
3109 }
3110
3111 /* This empties the queue */
3112 static guint
3113 count_queue (MonoLockFreeQueue *queue)
3114 {
3115         MonoLockFreeQueueNode *node;
3116         guint count = 0;
3117
3118         while ((node = mono_lock_free_queue_dequeue (queue))) {
3119                 count++;
3120                 mono_thread_hazardous_try_free (node, g_free);
3121         }
3122
3123         return count;
3124 }
3125
3126 static void
3127 build_class_buffer (gpointer key, gpointer value, gpointer userdata)
3128 {
3129         MonoClass *klass = (MonoClass *)key;
3130         MonoLockFreeQueue *class_methods = (MonoLockFreeQueue *)value;
3131         MonoImage *image;
3132         char *class_name;
3133         const char *assembly_name;
3134         int number_of_methods, partially_covered;
3135         guint fully_covered;
3136
3137         image = mono_class_get_image (klass);
3138         assembly_name = mono_image_get_name (image);
3139         class_name = mono_type_get_name (mono_class_get_type (klass));
3140
3141         assembly_name = assembly_name ? assembly_name : "";
3142         number_of_methods = mono_class_num_methods (klass);
3143         fully_covered = count_queue (class_methods);
3144         /* We don't handle partial covered yet */
3145         partially_covered = 0;
3146
3147         ENTER_LOG (&coverage_classes_ctr, logbuffer,
3148                 EVENT_SIZE /* event */ +
3149                 strlen (assembly_name) + 1 /* assembly name */ +
3150                 strlen (class_name) + 1 /* class name */ +
3151                 LEB128_SIZE /* no. methods */ +
3152                 LEB128_SIZE /* fully covered */ +
3153                 LEB128_SIZE /* partially covered */
3154         );
3155
3156         emit_event (logbuffer, TYPE_COVERAGE_CLASS | TYPE_COVERAGE);
3157         emit_string (logbuffer, assembly_name, strlen (assembly_name) + 1);
3158         emit_string (logbuffer, class_name, strlen (class_name) + 1);
3159         emit_uvalue (logbuffer, number_of_methods);
3160         emit_uvalue (logbuffer, fully_covered);
3161         emit_uvalue (logbuffer, partially_covered);
3162
3163         EXIT_LOG;
3164
3165         g_free (class_name);
3166 }
3167
3168 static void
3169 get_coverage_for_image (MonoImage *image, int *number_of_methods, guint *fully_covered, int *partially_covered)
3170 {
3171         MonoLockFreeQueue *image_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (log_profiler.coverage_image_to_methods, image);
3172
3173         *number_of_methods = mono_image_get_table_rows (image, MONO_TABLE_METHOD);
3174         if (image_methods)
3175                 *fully_covered = count_queue (image_methods);
3176         else
3177                 *fully_covered = 0;
3178
3179         // FIXME: We don't handle partially covered yet.
3180         *partially_covered = 0;
3181 }
3182
3183 static void
3184 build_assembly_buffer (gpointer key, gpointer value, gpointer userdata)
3185 {
3186         MonoAssembly *assembly = (MonoAssembly *)value;
3187         MonoImage *image = mono_assembly_get_image (assembly);
3188         const char *name, *guid, *filename;
3189         int number_of_methods = 0, partially_covered = 0;
3190         guint fully_covered = 0;
3191
3192         name = mono_image_get_name (image);
3193         guid = mono_image_get_guid (image);
3194         filename = mono_image_get_filename (image);
3195
3196         name = name ? name : "";
3197         guid = guid ? guid : "";
3198         filename = filename ? filename : "";
3199
3200         get_coverage_for_image (image, &number_of_methods, &fully_covered, &partially_covered);
3201
3202         ENTER_LOG (&coverage_assemblies_ctr, logbuffer,
3203                 EVENT_SIZE /* event */ +
3204                 strlen (name) + 1 /* name */ +
3205                 strlen (guid) + 1 /* guid */ +
3206                 strlen (filename) + 1 /* file name */ +
3207                 LEB128_SIZE /* no. methods */ +
3208                 LEB128_SIZE /* fully covered */ +
3209                 LEB128_SIZE /* partially covered */
3210         );
3211
3212         emit_event (logbuffer, TYPE_COVERAGE_ASSEMBLY | TYPE_COVERAGE);
3213         emit_string (logbuffer, name, strlen (name) + 1);
3214         emit_string (logbuffer, guid, strlen (guid) + 1);
3215         emit_string (logbuffer, filename, strlen (filename) + 1);
3216         emit_uvalue (logbuffer, number_of_methods);
3217         emit_uvalue (logbuffer, fully_covered);
3218         emit_uvalue (logbuffer, partially_covered);
3219
3220         EXIT_LOG;
3221 }
3222
3223 static void
3224 dump_coverage (void)
3225 {
3226         mono_os_mutex_lock (&log_profiler.coverage_mutex);
3227         mono_conc_hashtable_foreach (log_profiler.coverage_assemblies, build_assembly_buffer, NULL);
3228         mono_conc_hashtable_foreach (log_profiler.coverage_classes, build_class_buffer, NULL);
3229         mono_conc_hashtable_foreach (log_profiler.coverage_methods, build_method_buffer, NULL);
3230         mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3231 }
3232
3233 static MonoLockFreeQueueNode *
3234 create_method_node (MonoMethod *method)
3235 {
3236         MethodNode *node = (MethodNode *) g_malloc (sizeof (MethodNode));
3237         mono_lock_free_queue_node_init ((MonoLockFreeQueueNode *) node, FALSE);
3238         node->method = method;
3239
3240         return (MonoLockFreeQueueNode *) node;
3241 }
3242
3243 static gboolean
3244 coverage_filter (MonoProfiler *prof, MonoMethod *method)
3245 {
3246         MonoError error;
3247         MonoClass *klass;
3248         MonoImage *image;
3249         MonoAssembly *assembly;
3250         MonoMethodHeader *header;
3251         guint32 iflags, flags, code_size;
3252         char *fqn, *classname;
3253         gboolean has_positive, found;
3254         MonoLockFreeQueue *image_methods, *class_methods;
3255         MonoLockFreeQueueNode *node;
3256
3257         flags = mono_method_get_flags (method, &iflags);
3258         if ((iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
3259             (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
3260                 return FALSE;
3261
3262         // Don't need to do anything else if we're already tracking this method
3263         if (mono_conc_hashtable_lookup (log_profiler.coverage_methods, method))
3264                 return TRUE;
3265
3266         klass = mono_method_get_class (method);
3267         image = mono_class_get_image (klass);
3268
3269         // Don't handle coverage for the core assemblies
3270         if (mono_conc_hashtable_lookup (log_profiler.coverage_suppressed_assemblies, (gpointer) mono_image_get_name (image)) != NULL)
3271                 return FALSE;
3272
3273         if (prof->coverage_filters) {
3274                 /* Check already filtered classes first */
3275                 if (mono_conc_hashtable_lookup (log_profiler.coverage_filtered_classes, klass))
3276                         return FALSE;
3277
3278                 classname = mono_type_get_name (mono_class_get_type (klass));
3279
3280                 fqn = g_strdup_printf ("[%s]%s", mono_image_get_name (image), classname);
3281
3282                 // Check positive filters first
3283                 has_positive = FALSE;
3284                 found = FALSE;
3285                 for (guint i = 0; i < prof->coverage_filters->len; ++i) {
3286                         char *filter = (char *)g_ptr_array_index (prof->coverage_filters, i);
3287
3288                         if (filter [0] == '+') {
3289                                 filter = &filter [1];
3290
3291                                 if (strstr (fqn, filter) != NULL)
3292                                         found = TRUE;
3293
3294                                 has_positive = TRUE;
3295                         }
3296                 }
3297
3298                 if (has_positive && !found) {
3299                         mono_os_mutex_lock (&log_profiler.coverage_mutex);
3300                         mono_conc_hashtable_insert (log_profiler.coverage_filtered_classes, klass, klass);
3301                         mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3302                         g_free (fqn);
3303                         g_free (classname);
3304
3305                         return FALSE;
3306                 }
3307
3308                 for (guint i = 0; i < prof->coverage_filters->len; ++i) {
3309                         // FIXME: Is substring search sufficient?
3310                         char *filter = (char *)g_ptr_array_index (prof->coverage_filters, i);
3311                         if (filter [0] == '+')
3312                                 continue;
3313
3314                         // Skip '-'
3315                         filter = &filter [1];
3316
3317                         if (strstr (fqn, filter) != NULL) {
3318                                 mono_os_mutex_lock (&log_profiler.coverage_mutex);
3319                                 mono_conc_hashtable_insert (log_profiler.coverage_filtered_classes, klass, klass);
3320                                 mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3321                                 g_free (fqn);
3322                                 g_free (classname);
3323
3324                                 return FALSE;
3325                         }
3326                 }
3327
3328                 g_free (fqn);
3329                 g_free (classname);
3330         }
3331
3332         header = mono_method_get_header_checked (method, &error);
3333         mono_error_cleanup (&error);
3334
3335         mono_method_header_get_code (header, &code_size, NULL);
3336
3337         assembly = mono_image_get_assembly (image);
3338
3339         // Need to keep the assemblies around for as long as they are kept in the hashtable
3340         // Nunit, for example, has a habit of unloading them before the coverage statistics are
3341         // generated causing a crash. See https://bugzilla.xamarin.com/show_bug.cgi?id=39325
3342         mono_assembly_addref (assembly);
3343
3344         mono_os_mutex_lock (&log_profiler.coverage_mutex);
3345         mono_conc_hashtable_insert (log_profiler.coverage_methods, method, method);
3346         mono_conc_hashtable_insert (log_profiler.coverage_assemblies, assembly, assembly);
3347         mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3348
3349         image_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (log_profiler.coverage_image_to_methods, image);
3350
3351         if (image_methods == NULL) {
3352                 image_methods = (MonoLockFreeQueue *) g_malloc (sizeof (MonoLockFreeQueue));
3353                 mono_lock_free_queue_init (image_methods);
3354                 mono_os_mutex_lock (&log_profiler.coverage_mutex);
3355                 mono_conc_hashtable_insert (log_profiler.coverage_image_to_methods, image, image_methods);
3356                 mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3357         }
3358
3359         node = create_method_node (method);
3360         mono_lock_free_queue_enqueue (image_methods, node);
3361
3362         class_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (log_profiler.coverage_classes, klass);
3363
3364         if (class_methods == NULL) {
3365                 class_methods = (MonoLockFreeQueue *) g_malloc (sizeof (MonoLockFreeQueue));
3366                 mono_lock_free_queue_init (class_methods);
3367                 mono_os_mutex_lock (&log_profiler.coverage_mutex);
3368                 mono_conc_hashtable_insert (log_profiler.coverage_classes, klass, class_methods);
3369                 mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3370         }
3371
3372         node = create_method_node (method);
3373         mono_lock_free_queue_enqueue (class_methods, node);
3374
3375         return TRUE;
3376 }
3377
3378 #define LINE_BUFFER_SIZE 4096
3379 /* Max file limit of 128KB */
3380 #define MAX_FILE_SIZE 128 * 1024
3381 static char *
3382 get_file_content (FILE *stream)
3383 {
3384         char *buffer;
3385         ssize_t bytes_read;
3386         long filesize;
3387         int res, offset = 0;
3388
3389         res = fseek (stream, 0, SEEK_END);
3390         if (res < 0)
3391           return NULL;
3392
3393         filesize = ftell (stream);
3394         if (filesize < 0)
3395           return NULL;
3396
3397         res = fseek (stream, 0, SEEK_SET);
3398         if (res < 0)
3399           return NULL;
3400
3401         if (filesize > MAX_FILE_SIZE)
3402           return NULL;
3403
3404         buffer = (char *) g_malloc ((filesize + 1) * sizeof (char));
3405         while ((bytes_read = fread (buffer + offset, 1, LINE_BUFFER_SIZE, stream)) > 0)
3406                 offset += bytes_read;
3407
3408         /* NULL terminate our buffer */
3409         buffer[filesize] = '\0';
3410         return buffer;
3411 }
3412
3413 static char *
3414 get_next_line (char *contents, char **next_start)
3415 {
3416         char *p = contents;
3417
3418         if (p == NULL || *p == '\0') {
3419                 *next_start = NULL;
3420                 return NULL;
3421         }
3422
3423         while (*p != '\n' && *p != '\0')
3424                 p++;
3425
3426         if (*p == '\n') {
3427                 *p = '\0';
3428                 *next_start = p + 1;
3429         } else
3430                 *next_start = NULL;
3431
3432         return contents;
3433 }
3434
3435 static void
3436 init_suppressed_assemblies (void)
3437 {
3438         char *content;
3439         char *line;
3440         FILE *sa_file;
3441
3442         log_profiler.coverage_suppressed_assemblies = mono_conc_hashtable_new (g_str_hash, g_str_equal);
3443         sa_file = fopen (SUPPRESSION_DIR "/mono-profiler-log.suppression", "r");
3444         if (sa_file == NULL)
3445                 return;
3446
3447         /* Don't need to free @content as it is referred to by the lines stored in @suppressed_assemblies */
3448         content = get_file_content (sa_file);
3449         if (content == NULL)
3450                 g_error ("mono-profiler-log.suppression is greater than 128kb - aborting.");
3451
3452         while ((line = get_next_line (content, &content))) {
3453                 line = g_strchomp (g_strchug (line));
3454                 /* No locking needed as we're doing initialization */
3455                 mono_conc_hashtable_insert (log_profiler.coverage_suppressed_assemblies, line, line);
3456         }
3457
3458         fclose (sa_file);
3459 }
3460
3461 static void
3462 parse_cov_filter_file (GPtrArray *filters, const char *file)
3463 {
3464         FILE *filter_file = fopen (file, "r");
3465
3466         if (filter_file == NULL) {
3467                 mono_profiler_printf_err ("Could not open coverage filter file '%s'.", file);
3468                 return;
3469         }
3470
3471         /* Don't need to free content as it is referred to by the lines stored in @filters */
3472         char *content = get_file_content (filter_file);
3473
3474         if (content == NULL)
3475                 mono_profiler_printf_err ("Coverage filter file '%s' is larger than 128kb - ignoring.", file);
3476
3477         char *line;
3478
3479         while ((line = get_next_line (content, &content)))
3480                 g_ptr_array_add (filters, g_strchug (g_strchomp (line)));
3481
3482         fclose (filter_file);
3483 }
3484
3485 static void
3486 coverage_init (void)
3487 {
3488         mono_os_mutex_init (&log_profiler.coverage_mutex);
3489         log_profiler.coverage_methods = mono_conc_hashtable_new (NULL, NULL);
3490         log_profiler.coverage_assemblies = mono_conc_hashtable_new (NULL, NULL);
3491         log_profiler.coverage_classes = mono_conc_hashtable_new (NULL, NULL);
3492         log_profiler.coverage_filtered_classes = mono_conc_hashtable_new (NULL, NULL);
3493         log_profiler.coverage_image_to_methods = mono_conc_hashtable_new (NULL, NULL);
3494         init_suppressed_assemblies ();
3495 }
3496
3497 static void
3498 unref_coverage_assemblies (gpointer key, gpointer value, gpointer userdata)
3499 {
3500         MonoAssembly *assembly = (MonoAssembly *)value;
3501         mono_assembly_close (assembly);
3502 }
3503
3504 static void
3505 free_sample_hit (gpointer p)
3506 {
3507         mono_lock_free_free (p, SAMPLE_BLOCK_SIZE);
3508 }
3509
3510 static void
3511 cleanup_reusable_samples (void)
3512 {
3513         SampleHit *sample;
3514
3515         while ((sample = (SampleHit *) mono_lock_free_queue_dequeue (&log_profiler.sample_reuse_queue)))
3516                 mono_thread_hazardous_try_free (sample, free_sample_hit);
3517 }
3518
3519 static void
3520 log_early_shutdown (MonoProfiler *prof)
3521 {
3522         if (log_config.hs_on_shutdown) {
3523                 InterlockedWrite (&log_profiler.heapshot_requested, 1);
3524                 mono_gc_collect (mono_gc_max_generation ());
3525         }
3526 }
3527
3528 static void
3529 log_shutdown (MonoProfiler *prof)
3530 {
3531         InterlockedWrite (&log_profiler.in_shutdown, 1);
3532
3533         if (ENABLED (PROFLOG_COUNTER_EVENTS))
3534                 counters_and_perfcounters_sample ();
3535
3536         if (log_config.collect_coverage)
3537                 dump_coverage ();
3538
3539         char c = 1;
3540
3541         if (write (prof->pipes [1], &c, 1) != 1) {
3542                 mono_profiler_printf_err ("Could not write to log profiler pipe: %s", g_strerror (errno));
3543                 exit (1);
3544         }
3545
3546         mono_native_thread_join (prof->helper_thread);
3547
3548         mono_os_mutex_destroy (&log_profiler.counters_mutex);
3549
3550         MonoCounterAgent *mc_next;
3551
3552         for (MonoCounterAgent *cur = log_profiler.counters; cur; cur = mc_next) {
3553                 mc_next = cur->next;
3554                 g_free (cur);
3555         }
3556
3557         PerfCounterAgent *pc_next;
3558
3559         for (PerfCounterAgent *cur = log_profiler.perfcounters; cur; cur = pc_next) {
3560                 pc_next = cur->next;
3561                 g_free (cur);
3562         }
3563
3564         /*
3565          * Ensure that we empty the LLS completely, even if some nodes are
3566          * not immediately removed upon calling mono_lls_remove (), by
3567          * iterating until the head is NULL.
3568          */
3569         while (log_profiler.profiler_thread_list.head) {
3570                 MONO_LLS_FOREACH_SAFE (&log_profiler.profiler_thread_list, MonoProfilerThread, thread) {
3571                         g_assert (thread->attached && "Why is a thread in the LLS not attached?");
3572
3573                         remove_thread (thread);
3574                 } MONO_LLS_FOREACH_SAFE_END
3575         }
3576
3577         /*
3578          * Ensure that all threads have been freed, so that we don't miss any
3579          * buffers when we shut down the writer thread below.
3580          */
3581         mono_thread_hazardous_try_free_all ();
3582
3583         InterlockedWrite (&prof->run_dumper_thread, 0);
3584         mono_os_sem_post (&prof->dumper_queue_sem);
3585         mono_native_thread_join (prof->dumper_thread);
3586         mono_os_sem_destroy (&prof->dumper_queue_sem);
3587
3588         InterlockedWrite (&prof->run_writer_thread, 0);
3589         mono_os_sem_post (&prof->writer_queue_sem);
3590         mono_native_thread_join (prof->writer_thread);
3591         mono_os_sem_destroy (&prof->writer_queue_sem);
3592
3593         /*
3594          * Free all writer queue entries, and ensure that all sample hits will be
3595          * added to the sample reuse queue.
3596          */
3597         mono_thread_hazardous_try_free_all ();
3598
3599         cleanup_reusable_samples ();
3600
3601         /*
3602          * Finally, make sure that all sample hits are freed. This should cover all
3603          * hazardous data from the profiler. We can now be sure that the runtime
3604          * won't later invoke free functions in the profiler library after it has
3605          * been unloaded.
3606          */
3607         mono_thread_hazardous_try_free_all ();
3608
3609         gint32 state = InterlockedRead (&log_profiler.buffer_lock_state);
3610
3611         g_assert (!(state & 0xFFFF) && "Why is the reader count still non-zero?");
3612         g_assert (!(state >> 16) && "Why is the exclusive lock still held?");
3613
3614 #if defined (HAVE_SYS_ZLIB)
3615         if (prof->gzfile)
3616                 gzclose (prof->gzfile);
3617 #endif
3618         if (prof->pipe_output)
3619                 pclose (prof->file);
3620         else
3621                 fclose (prof->file);
3622
3623         mono_conc_hashtable_destroy (prof->method_table);
3624         mono_os_mutex_destroy (&prof->method_table_mutex);
3625
3626         if (log_config.collect_coverage) {
3627                 mono_os_mutex_lock (&log_profiler.coverage_mutex);
3628                 mono_conc_hashtable_foreach (log_profiler.coverage_assemblies, unref_coverage_assemblies, NULL);
3629                 mono_os_mutex_unlock (&log_profiler.coverage_mutex);
3630
3631                 mono_conc_hashtable_destroy (log_profiler.coverage_methods);
3632                 mono_conc_hashtable_destroy (log_profiler.coverage_assemblies);
3633                 mono_conc_hashtable_destroy (log_profiler.coverage_classes);
3634                 mono_conc_hashtable_destroy (log_profiler.coverage_filtered_classes);
3635
3636                 mono_conc_hashtable_destroy (log_profiler.coverage_image_to_methods);
3637                 mono_conc_hashtable_destroy (log_profiler.coverage_suppressed_assemblies);
3638                 mono_os_mutex_destroy (&log_profiler.coverage_mutex);
3639         }
3640
3641         mono_coop_mutex_destroy (&log_profiler.api_mutex);
3642
3643         PROF_TLS_FREE ();
3644
3645         g_free (prof->args);
3646 }
3647
3648 static char*
3649 new_filename (const char* filename)
3650 {
3651         time_t t = time (NULL);
3652         int pid = process_id ();
3653         char pid_buf [16];
3654         char time_buf [16];
3655         char *res, *d;
3656         const char *p;
3657         int count_dates = 0;
3658         int count_pids = 0;
3659         int s_date, s_pid;
3660         struct tm *ts;
3661         for (p = filename; *p; p++) {
3662                 if (*p != '%')
3663                         continue;
3664                 p++;
3665                 if (*p == 't')
3666                         count_dates++;
3667                 else if (*p == 'p')
3668                         count_pids++;
3669                 else if (*p == 0)
3670                         break;
3671         }
3672         if (!count_dates && !count_pids)
3673                 return pstrdup (filename);
3674         snprintf (pid_buf, sizeof (pid_buf), "%d", pid);
3675         ts = gmtime (&t);
3676         snprintf (time_buf, sizeof (time_buf), "%d%02d%02d%02d%02d%02d",
3677                 1900 + ts->tm_year, 1 + ts->tm_mon, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec);
3678         s_date = strlen (time_buf);
3679         s_pid = strlen (pid_buf);
3680         d = res = (char *) g_malloc (strlen (filename) + s_date * count_dates + s_pid * count_pids);
3681         for (p = filename; *p; p++) {
3682                 if (*p != '%') {
3683                         *d++ = *p;
3684                         continue;
3685                 }
3686                 p++;
3687                 if (*p == 't') {
3688                         strcpy (d, time_buf);
3689                         d += s_date;
3690                         continue;
3691                 } else if (*p == 'p') {
3692                         strcpy (d, pid_buf);
3693                         d += s_pid;
3694                         continue;
3695                 } else if (*p == '%') {
3696                         *d++ = '%';
3697                         continue;
3698                 } else if (*p == 0)
3699                         break;
3700                 *d++ = '%';
3701                 *d++ = *p;
3702         }
3703         *d = 0;
3704         return res;
3705 }
3706
3707 static void
3708 add_to_fd_set (fd_set *set, int fd, int *max_fd)
3709 {
3710         /*
3711          * This should only trigger for the basic FDs (server socket, pipes) at
3712          * startup if for some mysterious reason they're too large. In this case,
3713          * the profiler really can't function, and we're better off printing an
3714          * error and exiting.
3715          */
3716         if (fd >= FD_SETSIZE) {
3717                 mono_profiler_printf_err ("File descriptor is out of bounds for fd_set: %d", fd);
3718                 exit (1);
3719         }
3720
3721         FD_SET (fd, set);
3722
3723         if (*max_fd < fd)
3724                 *max_fd = fd;
3725 }
3726
3727 static void *
3728 helper_thread (void *arg)
3729 {
3730         mono_threads_attach_tools_thread ();
3731         mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler helper");
3732
3733         MonoProfilerThread *thread = init_thread (FALSE);
3734
3735         GArray *command_sockets = g_array_new (FALSE, FALSE, sizeof (int));
3736
3737         while (1) {
3738                 fd_set rfds;
3739                 int max_fd = -1;
3740
3741                 FD_ZERO (&rfds);
3742
3743                 add_to_fd_set (&rfds, log_profiler.server_socket, &max_fd);
3744                 add_to_fd_set (&rfds, log_profiler.pipes [0], &max_fd);
3745
3746                 for (gint i = 0; i < command_sockets->len; i++)
3747                         add_to_fd_set (&rfds, g_array_index (command_sockets, int, i), &max_fd);
3748
3749                 struct timeval tv = { .tv_sec = 1, .tv_usec = 0 };
3750
3751                 // Sleep for 1sec or until a file descriptor has data.
3752                 if (select (max_fd + 1, &rfds, NULL, NULL, &tv) == -1) {
3753                         if (errno == EINTR)
3754                                 continue;
3755
3756                         mono_profiler_printf_err ("Could not poll in log profiler helper thread: %s", g_strerror (errno));
3757                         exit (1);
3758                 }
3759
3760                 if (ENABLED (PROFLOG_COUNTER_EVENTS))
3761                         counters_and_perfcounters_sample ();
3762
3763                 buffer_lock_excl ();
3764
3765                 sync_point (SYNC_POINT_PERIODIC);
3766
3767                 buffer_unlock_excl ();
3768
3769                 // Are we shutting down?
3770                 if (FD_ISSET (log_profiler.pipes [0], &rfds)) {
3771                         char c;
3772                         read (log_profiler.pipes [0], &c, 1);
3773                         break;
3774                 }
3775
3776                 for (gint i = 0; i < command_sockets->len; i++) {
3777                         int fd = g_array_index (command_sockets, int, i);
3778
3779                         if (!FD_ISSET (fd, &rfds))
3780                                 continue;
3781
3782                         char buf [64];
3783                         int len = read (fd, buf, sizeof (buf) - 1);
3784
3785                         if (len == -1)
3786                                 continue;
3787
3788                         if (!len) {
3789                                 // The other end disconnected.
3790                                 g_array_remove_index (command_sockets, i);
3791                                 close (fd);
3792
3793                                 continue;
3794                         }
3795
3796                         buf [len] = 0;
3797
3798                         if (log_config.hs_mode == MONO_PROFILER_HEAPSHOT_ON_DEMAND && !strcmp (buf, "heapshot\n")) {
3799                                 // Rely on the finalization callback triggering a GC.
3800                                 InterlockedWrite (&log_profiler.heapshot_requested, 1);
3801                                 mono_gc_finalize_notify ();
3802                         }
3803                 }
3804
3805                 if (FD_ISSET (log_profiler.server_socket, &rfds)) {
3806                         int fd = accept (log_profiler.server_socket, NULL, NULL);
3807
3808                         if (fd != -1) {
3809                                 if (fd >= FD_SETSIZE)
3810                                         close (fd);
3811                                 else
3812                                         g_array_append_val (command_sockets, fd);
3813                         }
3814                 }
3815         }
3816
3817         for (gint i = 0; i < command_sockets->len; i++)
3818                 close (g_array_index (command_sockets, int, i));
3819
3820         g_array_free (command_sockets, TRUE);
3821
3822         send_log_unsafe (FALSE);
3823         deinit_thread (thread);
3824
3825         mono_thread_info_detach ();
3826
3827         return NULL;
3828 }
3829
3830 static void
3831 start_helper_thread (void)
3832 {
3833         if (pipe (log_profiler.pipes) == -1) {
3834                 mono_profiler_printf_err ("Could not create log profiler pipe: %s", g_strerror (errno));
3835                 exit (1);
3836         }
3837
3838         log_profiler.server_socket = socket (PF_INET, SOCK_STREAM, 0);
3839
3840         if (log_profiler.server_socket == -1) {
3841                 mono_profiler_printf_err ("Could not create log profiler server socket: %s", g_strerror (errno));
3842                 exit (1);
3843         }
3844
3845         struct sockaddr_in server_address;
3846
3847         memset (&server_address, 0, sizeof (server_address));
3848         server_address.sin_family = AF_INET;
3849         server_address.sin_addr.s_addr = INADDR_ANY;
3850         server_address.sin_port = htons (log_profiler.command_port);
3851
3852         if (bind (log_profiler.server_socket, (struct sockaddr *) &server_address, sizeof (server_address)) == -1) {
3853                 mono_profiler_printf_err ("Could not bind log profiler server socket on port %d: %s", log_profiler.command_port, g_strerror (errno));
3854                 close (log_profiler.server_socket);
3855                 exit (1);
3856         }
3857
3858         if (listen (log_profiler.server_socket, 1) == -1) {
3859                 mono_profiler_printf_err ("Could not listen on log profiler server socket: %s", g_strerror (errno));
3860                 close (log_profiler.server_socket);
3861                 exit (1);
3862         }
3863
3864         socklen_t slen = sizeof (server_address);
3865
3866         if (getsockname (log_profiler.server_socket, (struct sockaddr *) &server_address, &slen)) {
3867                 mono_profiler_printf_err ("Could not retrieve assigned port for log profiler server socket: %s", g_strerror (errno));
3868                 close (log_profiler.server_socket);
3869                 exit (1);
3870         }
3871
3872         log_profiler.command_port = ntohs (server_address.sin_port);
3873
3874         if (!mono_native_thread_create (&log_profiler.helper_thread, helper_thread, NULL)) {
3875                 mono_profiler_printf_err ("Could not start log profiler helper thread");
3876                 close (log_profiler.server_socket);
3877                 exit (1);
3878         }
3879 }
3880
3881 static void
3882 free_writer_entry (gpointer p)
3883 {
3884         mono_lock_free_free (p, WRITER_ENTRY_BLOCK_SIZE);
3885 }
3886
3887 static gboolean
3888 handle_writer_queue_entry (void)
3889 {
3890         WriterQueueEntry *entry;
3891
3892         if ((entry = (WriterQueueEntry *) mono_lock_free_queue_dequeue (&log_profiler.writer_queue))) {
3893                 if (!entry->methods)
3894                         goto no_methods;
3895
3896                 gboolean wrote_methods = FALSE;
3897
3898                 /*
3899                  * Encode the method events in a temporary log buffer that we
3900                  * flush to disk before the main buffer, ensuring that all
3901                  * methods have metadata emitted before they're referenced.
3902                  *
3903                  * We use a 'proper' thread-local buffer for this as opposed
3904                  * to allocating and freeing a buffer by hand because the call
3905                  * to mono_method_full_name () below may trigger class load
3906                  * events when it retrieves the signature of the method. So a
3907                  * thread-local buffer needs to exist when such events occur.
3908                  */
3909                 for (guint i = 0; i < entry->methods->len; i++) {
3910                         MethodInfo *info = (MethodInfo *) g_ptr_array_index (entry->methods, i);
3911
3912                         if (mono_conc_hashtable_lookup (log_profiler.method_table, info->method))
3913                                 goto free_info; // This method already has metadata emitted.
3914
3915                         /*
3916                          * Other threads use this hash table to get a general
3917                          * idea of whether a method has already been emitted to
3918                          * the stream. Due to the way we add to this table, it
3919                          * can easily happen that multiple threads queue up the
3920                          * same methods, but that's OK since eventually all
3921                          * methods will be in this table and the thread-local
3922                          * method lists will just be empty for the rest of the
3923                          * app's lifetime.
3924                          */
3925                         mono_os_mutex_lock (&log_profiler.method_table_mutex);
3926                         mono_conc_hashtable_insert (log_profiler.method_table, info->method, info->method);
3927                         mono_os_mutex_unlock (&log_profiler.method_table_mutex);
3928
3929                         char *name = mono_method_full_name (info->method, 1);
3930                         int nlen = strlen (name) + 1;
3931                         void *cstart = info->ji ? mono_jit_info_get_code_start (info->ji) : NULL;
3932                         int csize = info->ji ? mono_jit_info_get_code_size (info->ji) : 0;
3933
3934                         ENTER_LOG (&method_jits_ctr, logbuffer,
3935                                 EVENT_SIZE /* event */ +
3936                                 LEB128_SIZE /* method */ +
3937                                 LEB128_SIZE /* start */ +
3938                                 LEB128_SIZE /* size */ +
3939                                 nlen /* name */
3940                         );
3941
3942                         emit_event_time (logbuffer, TYPE_JIT | TYPE_METHOD, info->time);
3943                         emit_method_inner (logbuffer, info->method);
3944                         emit_ptr (logbuffer, cstart);
3945                         emit_value (logbuffer, csize);
3946
3947                         memcpy (logbuffer->cursor, name, nlen);
3948                         logbuffer->cursor += nlen;
3949
3950                         EXIT_LOG_EXPLICIT (NO_SEND);
3951
3952                         mono_free (name);
3953
3954                         wrote_methods = TRUE;
3955
3956                 free_info:
3957                         g_free (info);
3958                 }
3959
3960                 g_ptr_array_free (entry->methods, TRUE);
3961
3962                 if (wrote_methods) {
3963                         MonoProfilerThread *thread = PROF_TLS_GET ();
3964
3965                         dump_buffer_threadless (thread->buffer);
3966                         init_buffer_state (thread);
3967                 }
3968
3969         no_methods:
3970                 dump_buffer (entry->buffer);
3971
3972                 mono_thread_hazardous_try_free (entry, free_writer_entry);
3973
3974                 return TRUE;
3975         }
3976
3977         return FALSE;
3978 }
3979
3980 static void *
3981 writer_thread (void *arg)
3982 {
3983         mono_threads_attach_tools_thread ();
3984         mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler writer");
3985
3986         dump_header ();
3987
3988         MonoProfilerThread *thread = init_thread (FALSE);
3989
3990         while (InterlockedRead (&log_profiler.run_writer_thread)) {
3991                 mono_os_sem_wait (&log_profiler.writer_queue_sem, MONO_SEM_FLAGS_NONE);
3992                 handle_writer_queue_entry ();
3993         }
3994
3995         /* Drain any remaining entries on shutdown. */
3996         while (handle_writer_queue_entry ());
3997
3998         free_buffer (thread->buffer, thread->buffer->size);
3999         deinit_thread (thread);
4000
4001         mono_thread_info_detach ();
4002
4003         return NULL;
4004 }
4005
4006 static void
4007 start_writer_thread (void)
4008 {
4009         InterlockedWrite (&log_profiler.run_writer_thread, 1);
4010
4011         if (!mono_native_thread_create (&log_profiler.writer_thread, writer_thread, NULL)) {
4012                 mono_profiler_printf_err ("Could not start log profiler writer thread");
4013                 exit (1);
4014         }
4015 }
4016
4017 static void
4018 reuse_sample_hit (gpointer p)
4019 {
4020         SampleHit *sample = p;
4021
4022         mono_lock_free_queue_node_unpoison (&sample->node);
4023         mono_lock_free_queue_enqueue (&log_profiler.sample_reuse_queue, &sample->node);
4024 }
4025
4026 static gboolean
4027 handle_dumper_queue_entry (void)
4028 {
4029         SampleHit *sample;
4030
4031         if ((sample = (SampleHit *) mono_lock_free_queue_dequeue (&log_profiler.dumper_queue))) {
4032                 for (int i = 0; i < sample->count; ++i) {
4033                         MonoMethod *method = sample->frames [i].method;
4034                         MonoDomain *domain = sample->frames [i].domain;
4035                         void *address = sample->frames [i].base_address;
4036
4037                         if (!method) {
4038                                 g_assert (domain && "What happened to the domain pointer?");
4039                                 g_assert (address && "What happened to the instruction pointer?");
4040
4041                                 MonoJitInfo *ji = mono_jit_info_table_find (domain, (char *) address);
4042
4043                                 if (ji)
4044                                         sample->frames [i].method = mono_jit_info_get_method (ji);
4045                         }
4046                 }
4047
4048                 ENTER_LOG (&sample_hits_ctr, logbuffer,
4049                         EVENT_SIZE /* event */ +
4050                         LEB128_SIZE /* tid */ +
4051                         LEB128_SIZE /* count */ +
4052                         1 * (
4053                                 LEB128_SIZE /* ip */
4054                         ) +
4055                         LEB128_SIZE /* managed count */ +
4056                         sample->count * (
4057                                 LEB128_SIZE /* method */
4058                         )
4059                 );
4060
4061                 emit_event_time (logbuffer, TYPE_SAMPLE | TYPE_SAMPLE_HIT, sample->time);
4062                 emit_ptr (logbuffer, (void *) sample->tid);
4063                 emit_value (logbuffer, 1);
4064
4065                 // TODO: Actual native unwinding.
4066                 for (int i = 0; i < 1; ++i) {
4067                         emit_ptr (logbuffer, sample->ip);
4068                         add_code_pointer ((uintptr_t) sample->ip);
4069                 }
4070
4071                 /* new in data version 6 */
4072                 emit_uvalue (logbuffer, sample->count);
4073
4074                 for (int i = 0; i < sample->count; ++i)
4075                         emit_method (logbuffer, sample->frames [i].method);
4076
4077                 EXIT_LOG;
4078
4079                 mono_thread_hazardous_try_free (sample, reuse_sample_hit);
4080
4081                 dump_unmanaged_coderefs ();
4082         }
4083
4084         return FALSE;
4085 }
4086
4087 static void *
4088 dumper_thread (void *arg)
4089 {
4090         mono_threads_attach_tools_thread ();
4091         mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler dumper");
4092
4093         MonoProfilerThread *thread = init_thread (FALSE);
4094
4095         while (InterlockedRead (&log_profiler.run_dumper_thread)) {
4096                 /*
4097                  * Flush samples every second so it doesn't seem like the profiler is
4098                  * not working if the program is mostly idle.
4099                  */
4100                 if (mono_os_sem_timedwait (&log_profiler.dumper_queue_sem, 1000, MONO_SEM_FLAGS_NONE) == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT)
4101                         send_log_unsafe (FALSE);
4102
4103                 handle_dumper_queue_entry ();
4104         }
4105
4106         /* Drain any remaining entries on shutdown. */
4107         while (handle_dumper_queue_entry ());
4108
4109         send_log_unsafe (FALSE);
4110         deinit_thread (thread);
4111
4112         mono_thread_info_detach ();
4113
4114         return NULL;
4115 }
4116
4117 static void
4118 start_dumper_thread (void)
4119 {
4120         InterlockedWrite (&log_profiler.run_dumper_thread, 1);
4121
4122         if (!mono_native_thread_create (&log_profiler.dumper_thread, dumper_thread, NULL)) {
4123                 mono_profiler_printf_err ("Could not start log profiler dumper thread");
4124                 exit (1);
4125         }
4126 }
4127
4128 static void
4129 register_counter (const char *name, gint32 *counter)
4130 {
4131         mono_counters_register (name, MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, counter);
4132 }
4133
4134 ICALL_EXPORT gint32
4135 proflog_icall_GetMaxStackTraceFrames (void)
4136 {
4137         return MAX_FRAMES;
4138 }
4139
4140 ICALL_EXPORT gint32
4141 proflog_icall_GetStackTraceFrames (void)
4142 {
4143         return log_config.num_frames;
4144 }
4145
4146 ICALL_EXPORT void
4147 proflog_icall_SetStackTraceFrames (gint32 value)
4148 {
4149         log_config.num_frames = value;
4150 }
4151
4152 ICALL_EXPORT MonoProfilerHeapshotMode
4153 proflog_icall_GetHeapshotMode (void)
4154 {
4155         return log_config.hs_mode;
4156 }
4157
4158 ICALL_EXPORT void
4159 proflog_icall_SetHeapshotMode (MonoProfilerHeapshotMode value)
4160 {
4161         log_config.hs_mode = value;
4162 }
4163
4164 ICALL_EXPORT gint32
4165 proflog_icall_GetHeapshotMillisecondsFrequency (void)
4166 {
4167         return log_config.hs_freq_ms;
4168 }
4169
4170 ICALL_EXPORT void
4171 proflog_icall_SetHeapshotMillisecondsFrequency (gint32 value)
4172 {
4173         log_config.hs_freq_ms = value;
4174 }
4175
4176 ICALL_EXPORT gint32
4177 proflog_icall_GetHeapshotCollectionsFrequency (void)
4178 {
4179         return log_config.hs_freq_gc;
4180 }
4181
4182 ICALL_EXPORT void
4183 proflog_icall_SetHeapshotCollectionsFrequency (gint32 value)
4184 {
4185         log_config.hs_freq_gc = value;
4186 }
4187
4188 ICALL_EXPORT gint32
4189 proflog_icall_GetCallDepth (void)
4190 {
4191         return log_config.max_call_depth;
4192 }
4193
4194 ICALL_EXPORT void
4195 proflog_icall_SetCallDepth (gint32 value)
4196 {
4197         log_config.max_call_depth = value;
4198 }
4199
4200 ICALL_EXPORT void
4201 proflog_icall_GetSampleMode (MonoProfilerSampleMode *mode, gint32 *frequency)
4202 {
4203         uint32_t freq;
4204
4205         mono_profiler_get_sample_mode (log_profiler.handle, mode, &freq);
4206
4207         *frequency = freq;
4208 }
4209
4210 ICALL_EXPORT MonoBoolean
4211 proflog_icall_SetSampleMode (MonoProfilerSampleMode mode, gint32 frequency)
4212 {
4213         mono_coop_mutex_lock (&log_profiler.api_mutex);
4214
4215         mono_bool result = mono_profiler_set_sample_mode (log_profiler.handle, mode, frequency);
4216
4217         if (mode != MONO_PROFILER_SAMPLE_MODE_NONE) {
4218                 ENABLE (PROFLOG_SAMPLE_EVENTS);
4219                 mono_profiler_set_sample_hit_callback (log_profiler.handle, mono_sample_hit);
4220         } else {
4221                 DISABLE (PROFLOG_SAMPLE_EVENTS);
4222                 mono_profiler_set_sample_hit_callback (log_profiler.handle, NULL);
4223         }
4224
4225         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4226
4227         return result;
4228 }
4229
4230 ICALL_EXPORT MonoBoolean
4231 proflog_icall_GetExceptionEvents (void)
4232 {
4233         return ENABLED (PROFLOG_EXCEPTION_EVENTS);
4234 }
4235
4236 ICALL_EXPORT void
4237 proflog_icall_SetExceptionEvents (MonoBoolean value)
4238 {
4239         mono_coop_mutex_lock (&log_profiler.api_mutex);
4240
4241         if (value) {
4242                 ENABLE (PROFLOG_EXCEPTION_EVENTS);
4243                 mono_profiler_set_exception_throw_callback (log_profiler.handle, throw_exc);
4244                 mono_profiler_set_exception_clause_callback (log_profiler.handle, clause_exc);
4245         } else {
4246                 DISABLE (PROFLOG_EXCEPTION_EVENTS);
4247                 mono_profiler_set_exception_throw_callback (log_profiler.handle, NULL);
4248                 mono_profiler_set_exception_clause_callback (log_profiler.handle, NULL);
4249         }
4250
4251         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4252 }
4253
4254 ICALL_EXPORT MonoBoolean
4255 proflog_icall_GetMonitorEvents (void)
4256 {
4257         return ENABLED (PROFLOG_MONITOR_EVENTS);
4258 }
4259
4260 ICALL_EXPORT void
4261 proflog_icall_SetMonitorEvents (MonoBoolean value)
4262 {
4263         mono_coop_mutex_lock (&log_profiler.api_mutex);
4264
4265         if (value) {
4266                 ENABLE (PROFLOG_MONITOR_EVENTS);
4267                 mono_profiler_set_monitor_contention_callback (log_profiler.handle, monitor_contention);
4268                 mono_profiler_set_monitor_acquired_callback (log_profiler.handle, monitor_acquired);
4269                 mono_profiler_set_monitor_failed_callback (log_profiler.handle, monitor_failed);
4270         } else {
4271                 DISABLE (PROFLOG_MONITOR_EVENTS);
4272                 mono_profiler_set_monitor_contention_callback (log_profiler.handle, NULL);
4273                 mono_profiler_set_monitor_acquired_callback (log_profiler.handle, NULL);
4274                 mono_profiler_set_monitor_failed_callback (log_profiler.handle, NULL);
4275         }
4276
4277         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4278 }
4279
4280 ICALL_EXPORT MonoBoolean
4281 proflog_icall_GetGCEvents (void)
4282 {
4283         return ENABLED (PROFLOG_GC_EVENTS);
4284 }
4285
4286 ICALL_EXPORT void
4287 proflog_icall_SetGCEvents (MonoBoolean value)
4288 {
4289         mono_coop_mutex_lock (&log_profiler.api_mutex);
4290
4291         if (value)
4292                 ENABLE (PROFLOG_GC_EVENTS);
4293         else
4294                 DISABLE (PROFLOG_GC_EVENTS);
4295
4296         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4297 }
4298
4299 ICALL_EXPORT MonoBoolean
4300 proflog_icall_GetGCAllocationEvents (void)
4301 {
4302         return ENABLED (PROFLOG_GC_ALLOCATION_EVENTS);
4303 }
4304
4305 ICALL_EXPORT void
4306 proflog_icall_SetGCAllocationEvents (MonoBoolean value)
4307 {
4308         mono_coop_mutex_lock (&log_profiler.api_mutex);
4309
4310         if (value) {
4311                 ENABLE (PROFLOG_GC_ALLOCATION_EVENTS);
4312                 mono_profiler_set_gc_allocation_callback (log_profiler.handle, gc_alloc);
4313         } else {
4314                 DISABLE (PROFLOG_GC_ALLOCATION_EVENTS);
4315                 mono_profiler_set_gc_allocation_callback (log_profiler.handle, NULL);
4316         }
4317
4318         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4319 }
4320
4321 ICALL_EXPORT MonoBoolean
4322 proflog_icall_GetGCMoveEvents (void)
4323 {
4324         return ENABLED (PROFLOG_GC_MOVE_EVENTS);
4325 }
4326
4327 ICALL_EXPORT void
4328 proflog_icall_SetGCMoveEvents (MonoBoolean value)
4329 {
4330         mono_coop_mutex_lock (&log_profiler.api_mutex);
4331
4332         if (value) {
4333                 ENABLE (PROFLOG_GC_MOVE_EVENTS);
4334                 mono_profiler_set_gc_moves_callback (log_profiler.handle, gc_moves);
4335         } else {
4336                 DISABLE (PROFLOG_GC_MOVE_EVENTS);
4337                 mono_profiler_set_gc_moves_callback (log_profiler.handle, NULL);
4338         }
4339
4340         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4341 }
4342
4343 ICALL_EXPORT MonoBoolean
4344 proflog_icall_GetGCRootEvents (void)
4345 {
4346         return ENABLED (PROFLOG_GC_ROOT_EVENTS);
4347 }
4348
4349 ICALL_EXPORT void
4350 proflog_icall_SetGCRootEvents (MonoBoolean value)
4351 {
4352         mono_coop_mutex_lock (&log_profiler.api_mutex);
4353
4354         if (value)
4355                 ENABLE (PROFLOG_GC_ROOT_EVENTS);
4356         else
4357                 DISABLE (PROFLOG_GC_ROOT_EVENTS);
4358
4359         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4360 }
4361
4362 ICALL_EXPORT MonoBoolean
4363 proflog_icall_GetGCHandleEvents (void)
4364 {
4365         return ENABLED (PROFLOG_GC_HANDLE_EVENTS);
4366 }
4367
4368 ICALL_EXPORT void
4369 proflog_icall_SetGCHandleEvents (MonoBoolean value)
4370 {
4371         mono_coop_mutex_lock (&log_profiler.api_mutex);
4372
4373         if (value) {
4374                 ENABLE (PROFLOG_GC_HANDLE_EVENTS);
4375                 mono_profiler_set_gc_handle_created_callback (log_profiler.handle, gc_handle_created);
4376                 mono_profiler_set_gc_handle_deleted_callback (log_profiler.handle, gc_handle_deleted);
4377         } else {
4378                 DISABLE (PROFLOG_GC_HANDLE_EVENTS);
4379                 mono_profiler_set_gc_handle_created_callback (log_profiler.handle, NULL);
4380                 mono_profiler_set_gc_handle_deleted_callback (log_profiler.handle, NULL);
4381         }
4382
4383         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4384 }
4385
4386 ICALL_EXPORT MonoBoolean
4387 proflog_icall_GetGCFinalizationEvents (void)
4388 {
4389         return ENABLED (PROFLOG_GC_FINALIZATION_EVENTS);
4390 }
4391
4392 ICALL_EXPORT void
4393 proflog_icall_SetGCFinalizationEvents (MonoBoolean value)
4394 {
4395         mono_coop_mutex_lock (&log_profiler.api_mutex);
4396
4397         if (value) {
4398                 ENABLE (PROFLOG_GC_FINALIZATION_EVENTS);
4399                 mono_profiler_set_gc_finalizing_callback (log_profiler.handle, finalize_begin);
4400                 mono_profiler_set_gc_finalizing_object_callback (log_profiler.handle, finalize_object_begin);
4401                 mono_profiler_set_gc_finalized_object_callback (log_profiler.handle, finalize_object_end);
4402         } else {
4403                 DISABLE (PROFLOG_GC_FINALIZATION_EVENTS);
4404                 mono_profiler_set_gc_finalizing_callback (log_profiler.handle, NULL);
4405                 mono_profiler_set_gc_finalizing_object_callback (log_profiler.handle, NULL);
4406                 mono_profiler_set_gc_finalized_object_callback (log_profiler.handle, NULL);
4407         }
4408
4409         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4410 }
4411
4412 ICALL_EXPORT MonoBoolean
4413 proflog_icall_GetCounterEvents (void)
4414 {
4415         return ENABLED (PROFLOG_COUNTER_EVENTS);
4416 }
4417
4418 ICALL_EXPORT void
4419 proflog_icall_SetCounterEvents (MonoBoolean value)
4420 {
4421         mono_coop_mutex_lock (&log_profiler.api_mutex);
4422
4423         if (value)
4424                 ENABLE (PROFLOG_COUNTER_EVENTS);
4425         else
4426                 DISABLE (PROFLOG_COUNTER_EVENTS);
4427
4428         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4429 }
4430
4431 ICALL_EXPORT MonoBoolean
4432 proflog_icall_GetJitEvents (void)
4433 {
4434         return ENABLED (PROFLOG_JIT_EVENTS);
4435 }
4436
4437 ICALL_EXPORT void
4438 proflog_icall_SetJitEvents (MonoBoolean value)
4439 {
4440         mono_coop_mutex_lock (&log_profiler.api_mutex);
4441
4442         if (value) {
4443                 ENABLE (PROFLOG_JIT_EVENTS);
4444                 mono_profiler_set_jit_code_buffer_callback (log_profiler.handle, code_buffer_new);
4445         } else {
4446                 DISABLE (PROFLOG_JIT_EVENTS);
4447                 mono_profiler_set_jit_code_buffer_callback (log_profiler.handle, NULL);
4448         }
4449
4450         mono_coop_mutex_unlock (&log_profiler.api_mutex);
4451 }
4452
4453 static void
4454 runtime_initialized (MonoProfiler *profiler)
4455 {
4456         InterlockedWrite (&log_profiler.runtime_inited, 1);
4457
4458         register_counter ("Sample events allocated", &sample_allocations_ctr);
4459         register_counter ("Log buffers allocated", &buffer_allocations_ctr);
4460
4461         register_counter ("Event: Sync points", &sync_points_ctr);
4462         register_counter ("Event: Heap objects", &heap_objects_ctr);
4463         register_counter ("Event: Heap starts", &heap_starts_ctr);
4464         register_counter ("Event: Heap ends", &heap_ends_ctr);
4465         register_counter ("Event: Heap roots", &heap_roots_ctr);
4466         register_counter ("Event: GC events", &gc_events_ctr);
4467         register_counter ("Event: GC resizes", &gc_resizes_ctr);
4468         register_counter ("Event: GC allocations", &gc_allocs_ctr);
4469         register_counter ("Event: GC moves", &gc_moves_ctr);
4470         register_counter ("Event: GC handle creations", &gc_handle_creations_ctr);
4471         register_counter ("Event: GC handle deletions", &gc_handle_deletions_ctr);
4472         register_counter ("Event: GC finalize starts", &finalize_begins_ctr);
4473         register_counter ("Event: GC finalize ends", &finalize_ends_ctr);
4474         register_counter ("Event: GC finalize object starts", &finalize_object_begins_ctr);
4475         register_counter ("Event: GC finalize object ends", &finalize_object_ends_ctr);
4476         register_counter ("Event: Image loads", &image_loads_ctr);
4477         register_counter ("Event: Image unloads", &image_unloads_ctr);
4478         register_counter ("Event: Assembly loads", &assembly_loads_ctr);
4479         register_counter ("Event: Assembly unloads", &assembly_unloads_ctr);
4480         register_counter ("Event: Class loads", &class_loads_ctr);
4481         register_counter ("Event: Class unloads", &class_unloads_ctr);
4482         register_counter ("Event: Method entries", &method_entries_ctr);
4483         register_counter ("Event: Method exits", &method_exits_ctr);
4484         register_counter ("Event: Method exception leaves", &method_exception_exits_ctr);
4485         register_counter ("Event: Method JITs", &method_jits_ctr);
4486         register_counter ("Event: Code buffers", &code_buffers_ctr);
4487         register_counter ("Event: Exception throws", &exception_throws_ctr);
4488         register_counter ("Event: Exception clauses", &exception_clauses_ctr);
4489         register_counter ("Event: Monitor events", &monitor_events_ctr);
4490         register_counter ("Event: Thread starts", &thread_starts_ctr);
4491         register_counter ("Event: Thread ends", &thread_ends_ctr);
4492         register_counter ("Event: Thread names", &thread_names_ctr);
4493         register_counter ("Event: Domain loads", &domain_loads_ctr);
4494         register_counter ("Event: Domain unloads", &domain_unloads_ctr);
4495         register_counter ("Event: Domain names", &domain_names_ctr);
4496         register_counter ("Event: Context loads", &context_loads_ctr);
4497         register_counter ("Event: Context unloads", &context_unloads_ctr);
4498         register_counter ("Event: Sample binaries", &sample_ubins_ctr);
4499         register_counter ("Event: Sample symbols", &sample_usyms_ctr);
4500         register_counter ("Event: Sample hits", &sample_hits_ctr);
4501         register_counter ("Event: Counter descriptors", &counter_descriptors_ctr);
4502         register_counter ("Event: Counter samples", &counter_samples_ctr);
4503         register_counter ("Event: Performance counter descriptors", &perfcounter_descriptors_ctr);
4504         register_counter ("Event: Performance counter samples", &perfcounter_samples_ctr);
4505         register_counter ("Event: Coverage methods", &coverage_methods_ctr);
4506         register_counter ("Event: Coverage statements", &coverage_statements_ctr);
4507         register_counter ("Event: Coverage classes", &coverage_classes_ctr);
4508         register_counter ("Event: Coverage assemblies", &coverage_assemblies_ctr);
4509
4510         counters_init ();
4511
4512         /*
4513          * We must start the helper thread before the writer thread. This is
4514          * because the helper thread sets up the command port which is written to
4515          * the log header by the writer thread.
4516          */
4517         start_helper_thread ();
4518         start_writer_thread ();
4519         start_dumper_thread ();
4520
4521         mono_coop_mutex_init (&log_profiler.api_mutex);
4522
4523 #define ADD_ICALL(NAME) \
4524         mono_add_internal_call ("Mono.Profiler.Log.LogProfiler::" EGLIB_STRINGIFY (NAME), proflog_icall_ ## NAME);
4525
4526         ADD_ICALL (GetMaxStackTraceFrames);
4527         ADD_ICALL (GetStackTraceFrames);
4528         ADD_ICALL (SetStackTraceFrames);
4529         ADD_ICALL (GetHeapshotMode);
4530         ADD_ICALL (SetHeapshotMode);
4531         ADD_ICALL (GetHeapshotMillisecondsFrequency);
4532         ADD_ICALL (SetHeapshotMillisecondsFrequency);
4533         ADD_ICALL (GetHeapshotCollectionsFrequency);
4534         ADD_ICALL (SetHeapshotCollectionsFrequency);
4535         ADD_ICALL (GetCallDepth);
4536         ADD_ICALL (SetCallDepth);
4537         ADD_ICALL (GetSampleMode);
4538         ADD_ICALL (SetSampleMode);
4539         ADD_ICALL (GetExceptionEvents);
4540         ADD_ICALL (SetExceptionEvents);
4541         ADD_ICALL (GetMonitorEvents);
4542         ADD_ICALL (SetMonitorEvents);
4543         ADD_ICALL (GetGCEvents);
4544         ADD_ICALL (SetGCEvents);
4545         ADD_ICALL (GetGCAllocationEvents);
4546         ADD_ICALL (SetGCAllocationEvents);
4547         ADD_ICALL (GetGCMoveEvents);
4548         ADD_ICALL (SetGCMoveEvents);
4549         ADD_ICALL (GetGCRootEvents);
4550         ADD_ICALL (SetGCRootEvents);
4551         ADD_ICALL (GetGCHandleEvents);
4552         ADD_ICALL (SetGCHandleEvents);
4553         ADD_ICALL (GetGCFinalizationEvents);
4554         ADD_ICALL (SetGCFinalizationEvents);
4555         ADD_ICALL (GetCounterEvents);
4556         ADD_ICALL (SetCounterEvents);
4557         ADD_ICALL (GetJitEvents);
4558         ADD_ICALL (SetJitEvents);
4559
4560 #undef ADD_ICALL
4561 }
4562
4563 static void
4564 create_profiler (const char *args, const char *filename, GPtrArray *filters)
4565 {
4566         char *nf;
4567
4568         log_profiler.args = pstrdup (args);
4569         log_profiler.command_port = log_config.command_port;
4570
4571         //If filename begin with +, append the pid at the end
4572         if (filename && *filename == '+')
4573                 filename = g_strdup_printf ("%s.%d", filename + 1, getpid ());
4574
4575         if (!filename) {
4576                 if (log_config.do_report)
4577                         filename = "|mprof-report -";
4578                 else
4579                         filename = "output.mlpd";
4580                 nf = (char*)filename;
4581         } else {
4582                 nf = new_filename (filename);
4583                 if (log_config.do_report) {
4584                         int s = strlen (nf) + 32;
4585                         char *p = (char *) g_malloc (s);
4586                         snprintf (p, s, "|mprof-report '--out=%s' -", nf);
4587                         g_free (nf);
4588                         nf = p;
4589                 }
4590         }
4591         if (*nf == '|') {
4592                 log_profiler.file = popen (nf + 1, "w");
4593                 log_profiler.pipe_output = 1;
4594         } else if (*nf == '#') {
4595                 int fd = strtol (nf + 1, NULL, 10);
4596                 log_profiler.file = fdopen (fd, "a");
4597         } else
4598                 log_profiler.file = fopen (nf, "wb");
4599
4600         if (!log_profiler.file) {
4601                 mono_profiler_printf_err ("Could not create log profiler output file '%s'.", nf);
4602                 exit (1);
4603         }
4604
4605 #if defined (HAVE_SYS_ZLIB)
4606         if (log_config.use_zip)
4607                 log_profiler.gzfile = gzdopen (fileno (log_profiler.file), "wb");
4608 #endif
4609
4610         /*
4611          * If you hit this assert while increasing MAX_FRAMES, you need to increase
4612          * SAMPLE_BLOCK_SIZE as well.
4613          */
4614         g_assert (SAMPLE_SLOT_SIZE (MAX_FRAMES) * 2 < LOCK_FREE_ALLOC_SB_USABLE_SIZE (SAMPLE_BLOCK_SIZE));
4615
4616         // FIXME: We should free this stuff too.
4617         mono_lock_free_allocator_init_size_class (&log_profiler.sample_size_class, SAMPLE_SLOT_SIZE (log_config.num_frames), SAMPLE_BLOCK_SIZE);
4618         mono_lock_free_allocator_init_allocator (&log_profiler.sample_allocator, &log_profiler.sample_size_class, MONO_MEM_ACCOUNT_PROFILER);
4619
4620         mono_lock_free_queue_init (&log_profiler.sample_reuse_queue);
4621
4622         g_assert (sizeof (WriterQueueEntry) * 2 < LOCK_FREE_ALLOC_SB_USABLE_SIZE (WRITER_ENTRY_BLOCK_SIZE));
4623
4624         // FIXME: We should free this stuff too.
4625         mono_lock_free_allocator_init_size_class (&log_profiler.writer_entry_size_class, sizeof (WriterQueueEntry), WRITER_ENTRY_BLOCK_SIZE);
4626         mono_lock_free_allocator_init_allocator (&log_profiler.writer_entry_allocator, &log_profiler.writer_entry_size_class, MONO_MEM_ACCOUNT_PROFILER);
4627
4628         mono_lock_free_queue_init (&log_profiler.writer_queue);
4629         mono_os_sem_init (&log_profiler.writer_queue_sem, 0);
4630
4631         mono_lock_free_queue_init (&log_profiler.dumper_queue);
4632         mono_os_sem_init (&log_profiler.dumper_queue_sem, 0);
4633
4634         mono_os_mutex_init (&log_profiler.method_table_mutex);
4635         log_profiler.method_table = mono_conc_hashtable_new (NULL, NULL);
4636
4637         if (log_config.collect_coverage)
4638                 coverage_init ();
4639
4640         log_profiler.coverage_filters = filters;
4641
4642         log_profiler.startup_time = current_time ();
4643 }
4644
4645 MONO_API void
4646 mono_profiler_init_log (const char *desc);
4647
4648 void
4649 mono_profiler_init_log (const char *desc)
4650 {
4651         GPtrArray *filters = NULL;
4652
4653         proflog_parse_args (&log_config, desc [3] == ':' ? desc + 4 : "");
4654
4655         if (log_config.cov_filter_files) {
4656                 filters = g_ptr_array_new ();
4657                 int i;
4658                 for (i = 0; i < log_config.cov_filter_files->len; ++i) {
4659                         const char *name = log_config.cov_filter_files->pdata [i];
4660                         parse_cov_filter_file (filters, name);
4661                 }
4662         }
4663
4664         init_time ();
4665
4666         PROF_TLS_INIT ();
4667
4668         create_profiler (desc, log_config.output_filename, filters);
4669
4670         mono_lls_init (&log_profiler.profiler_thread_list, NULL);
4671
4672         MonoProfilerHandle handle = log_profiler.handle = mono_profiler_create (&log_profiler);
4673
4674         /*
4675          * Required callbacks. These are either necessary for the profiler itself
4676          * to function, or provide metadata that's needed if other events (e.g.
4677          * allocations, exceptions) are dynamically enabled/disabled.
4678          */
4679
4680         mono_profiler_set_runtime_shutdown_begin_callback (handle, log_early_shutdown);
4681         mono_profiler_set_runtime_shutdown_end_callback (handle, log_shutdown);
4682         mono_profiler_set_runtime_initialized_callback (handle, runtime_initialized);
4683
4684         mono_profiler_set_gc_event_callback (handle, gc_event);
4685
4686         mono_profiler_set_thread_started_callback (handle, thread_start);
4687         mono_profiler_set_thread_stopped_callback (handle, thread_end);
4688         mono_profiler_set_thread_name_callback (handle, thread_name);
4689
4690         mono_profiler_set_domain_loaded_callback (handle, domain_loaded);
4691         mono_profiler_set_domain_unloading_callback (handle, domain_unloaded);
4692         mono_profiler_set_domain_name_callback (handle, domain_name);
4693
4694         mono_profiler_set_context_loaded_callback (handle, context_loaded);
4695         mono_profiler_set_context_unloaded_callback (handle, context_unloaded);
4696
4697         mono_profiler_set_assembly_loaded_callback (handle, assembly_loaded);
4698         mono_profiler_set_assembly_unloading_callback (handle, assembly_unloaded);
4699
4700         mono_profiler_set_image_loaded_callback (handle, image_loaded);
4701         mono_profiler_set_image_unloading_callback (handle, image_unloaded);
4702
4703         mono_profiler_set_class_loaded_callback (handle, class_loaded);
4704
4705         mono_profiler_set_jit_done_callback (handle, method_jitted);
4706
4707         if (ENABLED (PROFLOG_EXCEPTION_EVENTS)) {
4708                 mono_profiler_set_exception_throw_callback (handle, throw_exc);
4709                 mono_profiler_set_exception_clause_callback (handle, clause_exc);
4710         }
4711
4712         if (ENABLED (PROFLOG_MONITOR_EVENTS)) {
4713                 mono_profiler_set_monitor_contention_callback (handle, monitor_contention);
4714                 mono_profiler_set_monitor_acquired_callback (handle, monitor_acquired);
4715                 mono_profiler_set_monitor_failed_callback (handle, monitor_failed);
4716         }
4717
4718         if (ENABLED (PROFLOG_GC_EVENTS))
4719                 mono_profiler_set_gc_resize_callback (handle, gc_resize);
4720
4721         if (ENABLED (PROFLOG_GC_ALLOCATION_EVENTS))
4722                 mono_profiler_set_gc_allocation_callback (handle, gc_alloc);
4723
4724         if (ENABLED (PROFLOG_GC_MOVE_EVENTS))
4725                 mono_profiler_set_gc_moves_callback (handle, gc_moves);
4726
4727         if (ENABLED (PROFLOG_GC_ROOT_EVENTS))
4728                 mono_profiler_set_gc_roots_callback (handle, gc_roots);
4729
4730         if (ENABLED (PROFLOG_GC_HANDLE_EVENTS)) {
4731                 mono_profiler_set_gc_handle_created_callback (handle, gc_handle_created);
4732                 mono_profiler_set_gc_handle_deleted_callback (handle, gc_handle_deleted);
4733         }
4734
4735         if (ENABLED (PROFLOG_GC_FINALIZATION_EVENTS)) {
4736                 mono_profiler_set_gc_finalizing_callback (handle, finalize_begin);
4737                 mono_profiler_set_gc_finalized_callback (handle, finalize_end);
4738                 mono_profiler_set_gc_finalizing_object_callback (handle, finalize_object_begin);
4739         }
4740
4741         //On Demand heapshot uses the finalizer thread to force a collection and thus a heapshot
4742         mono_profiler_set_gc_finalized_callback (handle, finalize_end);
4743
4744         if (ENABLED (PROFLOG_SAMPLE_EVENTS))
4745                 mono_profiler_set_sample_hit_callback (handle, mono_sample_hit);
4746
4747         if (ENABLED (PROFLOG_JIT_EVENTS))
4748                 mono_profiler_set_jit_code_buffer_callback (handle, code_buffer_new);
4749
4750         if (log_config.enter_leave) {
4751                 mono_profiler_set_call_instrumentation_filter_callback (handle, method_filter);
4752                 mono_profiler_set_method_enter_callback (handle, method_enter);
4753                 mono_profiler_set_method_leave_callback (handle, method_leave);
4754                 mono_profiler_set_method_tail_call_callback (handle, tail_call);
4755                 mono_profiler_set_method_exception_leave_callback (handle, method_exc_leave);
4756         }
4757
4758         if (log_config.collect_coverage) {
4759                 mono_profiler_enable_coverage ();
4760                 mono_profiler_set_coverage_filter_callback (handle, coverage_filter);
4761         }
4762
4763         mono_profiler_enable_allocations ();
4764         mono_profiler_enable_sampling (handle);
4765
4766         /*
4767          * If no sample option was given by the user, this just leaves the sampling
4768          * thread in idle mode. We do this even if no option was given so that we
4769          * can warn if another profiler controls sampling parameters.
4770          */
4771         if (!mono_profiler_set_sample_mode (handle, log_config.sampling_mode, log_config.sample_freq))
4772                 mono_profiler_printf_err ("Another profiler controls sampling parameters; the log profiler will not be able to modify them.");
4773 }