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