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