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