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