Merge pull request #3489 from akoeplinger/fix-latin1-surrogatepair
[mono.git] / mono / metadata / profiler.c
1 /*
2  * profiler.c: Profiler interface for Mono
3  *
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *   Alex Rønne Petersen (alexrp@xamarin.com)
7  *
8  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10  * Copyright 2011 Xamarin Inc (http://www.xamarin.com).
11  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12  */
13
14 #include "config.h"
15 #include "mono/metadata/profiler-private.h"
16 #include "mono/metadata/assembly.h"
17 #include "mono/metadata/debug-helpers.h"
18 #include "mono/metadata/mono-debug.h"
19 #include "mono/metadata/debug-mono-symfile.h"
20 #include "mono/metadata/metadata-internals.h"
21 #include "mono/metadata/class-internals.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/gc-internals.h"
24 #include "mono/metadata/mono-config-dirs.h"
25 #include "mono/io-layer/io-layer.h"
26 #include "mono/utils/mono-dl.h"
27 #include <mono/utils/mono-logger-internals.h>
28 #include <string.h>
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32 #ifdef HAVE_SYS_TIME_H
33 #include <sys/time.h>
34 #endif
35 #ifdef HAVE_BACKTRACE_SYMBOLS
36 #include <execinfo.h>
37 #endif
38
39 typedef struct _ProfilerDesc ProfilerDesc;
40 struct _ProfilerDesc {
41         ProfilerDesc *next;
42         MonoProfiler *profiler;
43         MonoProfileFlags events;
44
45         MonoProfileAppDomainFunc   domain_start_load;
46         MonoProfileAppDomainResult domain_end_load;
47         MonoProfileAppDomainFunc   domain_start_unload;
48         MonoProfileAppDomainFunc   domain_end_unload;
49         MonoProfileAppDomainFriendlyNameFunc   domain_name;
50
51         MonoProfileContextFunc context_load;
52         MonoProfileContextFunc context_unload;
53
54         MonoProfileAssemblyFunc   assembly_start_load;
55         MonoProfileAssemblyResult assembly_end_load;
56         MonoProfileAssemblyFunc   assembly_start_unload;
57         MonoProfileAssemblyFunc   assembly_end_unload;
58
59         MonoProfileModuleFunc   module_start_load;
60         MonoProfileModuleResult module_end_load;
61         MonoProfileModuleFunc   module_start_unload;
62         MonoProfileModuleFunc   module_end_unload;
63
64         MonoProfileClassFunc   class_start_load;
65         MonoProfileClassResult class_end_load;
66         MonoProfileClassFunc   class_start_unload;
67         MonoProfileClassFunc   class_end_unload;
68
69         MonoProfileMethodFunc   jit_start;
70         MonoProfileMethodResult jit_end;
71         MonoProfileJitResult    jit_end2;
72         MonoProfileMethodFunc   method_free;
73         MonoProfileMethodFunc   method_start_invoke;
74         MonoProfileMethodFunc   method_end_invoke;
75         MonoProfileMethodResult man_unman_transition;
76         MonoProfileAllocFunc    allocation_cb;
77         MonoProfileMonitorFunc  monitor_event_cb;
78         MonoProfileStatFunc     statistical_cb;
79         MonoProfileStatCallChainFunc statistical_call_chain_cb;
80         int                     statistical_call_chain_depth;
81         MonoProfilerCallChainStrategy  statistical_call_chain_strategy;
82         MonoProfileMethodFunc   method_enter;
83         MonoProfileMethodFunc   method_leave;
84
85         MonoProfileExceptionFunc        exception_throw_cb;
86         MonoProfileMethodFunc exception_method_leave_cb;
87         MonoProfileExceptionClauseFunc exception_clause_cb;
88
89         MonoProfileIomapFunc iomap_cb;
90
91         MonoProfileThreadFunc   thread_start;
92         MonoProfileThreadFunc   thread_end;
93         MonoProfileThreadNameFunc   thread_name;
94
95         MonoProfileCoverageFilterFunc coverage_filter_cb;
96
97         MonoProfileFunc shutdown_callback;
98
99         MonoProfileGCFunc        gc_event;
100         MonoProfileGCResizeFunc  gc_heap_resize;
101         MonoProfileGCMoveFunc    gc_moves;
102         MonoProfileGCHandleFunc  gc_handle;
103         MonoProfileGCRootFunc    gc_roots;
104
105         MonoProfileGCFinalizeFunc gc_finalize_begin;
106         MonoProfileGCFinalizeObjectFunc gc_finalize_object_begin;
107         MonoProfileGCFinalizeObjectFunc gc_finalize_object_end;
108         MonoProfileGCFinalizeFunc gc_finalize_end;
109
110         MonoProfileFunc          runtime_initialized_event;
111
112         MonoProfilerCodeChunkNew code_chunk_new;
113         MonoProfilerCodeChunkDestroy code_chunk_destroy;
114         MonoProfilerCodeBufferNew code_buffer_new;
115 };
116
117 static ProfilerDesc *prof_list = NULL;
118
119 #define mono_profiler_coverage_lock() mono_os_mutex_lock (&profiler_coverage_mutex)
120 #define mono_profiler_coverage_unlock() mono_os_mutex_unlock (&profiler_coverage_mutex)
121 static mono_mutex_t profiler_coverage_mutex;
122
123 /* this is directly accessible to other mono libs.
124  * It is the ORed value of all the profiler's events.
125  */
126 MonoProfileFlags mono_profiler_events;
127
128 /**
129  * mono_profiler_install:
130  * @prof: a MonoProfiler structure pointer, or a pointer to a derived structure.
131  * @callback: the function to invoke at shutdown
132  *
133  * Use mono_profiler_install to activate profiling in the Mono runtime.
134  * Typically developers of new profilers will create a new structure whose
135  * first field is a MonoProfiler and put any extra information that they need
136  * to access from the various profiling callbacks there.
137  *
138  */
139 void
140 mono_profiler_install (MonoProfiler *prof, MonoProfileFunc callback)
141 {
142         ProfilerDesc *desc = g_new0 (ProfilerDesc, 1);
143         if (!prof_list)
144                 mono_os_mutex_init_recursive (&profiler_coverage_mutex);
145         desc->profiler = prof;
146         desc->shutdown_callback = callback;
147         desc->next = prof_list;
148         prof_list = desc;
149 }
150
151 /**
152  * mono_profiler_set_events:
153  * @events: an ORed set of values made up of MONO_PROFILER_ flags
154  *
155  * The events descriped in the @events argument is a set of flags
156  * that represent which profiling events must be triggered.  For
157  * example if you have registered a set of methods for tracking
158  * JIT compilation start and end with mono_profiler_install_jit_compile,
159  * you will want to pass the MONO_PROFILE_JIT_COMPILATION flag to
160  * this routine.
161  *
162  * You can call mono_profile_set_events more than once and you can
163  * do this at runtime to modify which methods are invoked.
164  */
165 void
166 mono_profiler_set_events (MonoProfileFlags events)
167 {
168         ProfilerDesc *prof;
169         MonoProfileFlags value = (MonoProfileFlags)0;
170         if (prof_list)
171                 prof_list->events = events;
172         for (prof = prof_list; prof; prof = prof->next)
173                 value = (MonoProfileFlags)(value | prof->events);
174         mono_profiler_events = value;
175 }
176
177 /**
178  * mono_profiler_get_events:
179  *
180  * Returns a list of active events that will be intercepted. 
181  */
182 MonoProfileFlags
183 mono_profiler_get_events (void)
184 {
185         return mono_profiler_events;
186 }
187
188 /**
189  * mono_profiler_install_enter_leave:
190  * @enter: the routine to be called on each method entry
191  * @fleave: the routine to be called each time a method returns
192  *
193  * Use this routine to install routines that will be called everytime
194  * a method enters and leaves.   The routines will receive as an argument
195  * the MonoMethod representing the method that is entering or leaving.
196  */
197 void
198 mono_profiler_install_enter_leave (MonoProfileMethodFunc enter, MonoProfileMethodFunc fleave)
199 {
200         if (!prof_list)
201                 return;
202         prof_list->method_enter = enter;
203         prof_list->method_leave = fleave;
204 }
205
206 /**
207  * mono_profiler_install_jit_compile:
208  * @start: the routine to be called when the JIT process starts.
209  * @end: the routine to be called when the JIT process ends.
210  *
211  * Use this routine to install routines that will be called when JIT 
212  * compilation of a method starts and completes.
213  */
214 void 
215 mono_profiler_install_jit_compile (MonoProfileMethodFunc start, MonoProfileMethodResult end)
216 {
217         if (!prof_list)
218                 return;
219         prof_list->jit_start = start;
220         prof_list->jit_end = end;
221 }
222
223 void 
224 mono_profiler_install_jit_end (MonoProfileJitResult end)
225 {
226         if (!prof_list)
227                 return;
228         prof_list->jit_end2 = end;
229 }
230
231 void 
232 mono_profiler_install_method_free (MonoProfileMethodFunc callback)
233 {
234         if (!prof_list)
235                 return;
236         prof_list->method_free = callback;
237 }
238
239 void
240 mono_profiler_install_method_invoke (MonoProfileMethodFunc start, MonoProfileMethodFunc end)
241 {
242         if (!prof_list)
243                 return;
244         prof_list->method_start_invoke = start;
245         prof_list->method_end_invoke = end;
246 }
247
248 void 
249 mono_profiler_install_thread (MonoProfileThreadFunc start, MonoProfileThreadFunc end)
250 {
251         if (!prof_list)
252                 return;
253         prof_list->thread_start = start;
254         prof_list->thread_end = end;
255 }
256
257 void 
258 mono_profiler_install_thread_name (MonoProfileThreadNameFunc thread_name_cb)
259 {
260         if (!prof_list)
261                 return;
262         prof_list->thread_name = thread_name_cb;
263 }
264
265 void 
266 mono_profiler_install_transition (MonoProfileMethodResult callback)
267 {
268         if (!prof_list)
269                 return;
270         prof_list->man_unman_transition = callback;
271 }
272
273 void 
274 mono_profiler_install_allocation (MonoProfileAllocFunc callback)
275 {
276         mono_gc_enable_alloc_events ();
277         if (!prof_list)
278                 return;
279         prof_list->allocation_cb = callback;
280 }
281
282 void
283 mono_profiler_install_monitor  (MonoProfileMonitorFunc callback)
284 {
285         if (!prof_list)
286                 return;
287         prof_list->monitor_event_cb = callback;
288 }
289
290 static MonoProfileSamplingMode sampling_mode = MONO_PROFILER_STAT_MODE_PROCESS;
291 static int64_t sampling_frequency = 100; // Hz
292
293 /**
294  * mono_profiler_set_statistical_mode:
295  * @mode the sampling mode used.
296  * @sample_frequency_is_us the sampling frequency in microseconds.
297  *
298  * Set the sampling parameters for the profiler. Sampling mode affects the effective sampling rate as in samples/s you'll witness.
299  * The default sampling mode is process mode, which only reports samples when there's activity in the process.
300  *
301  * Sampling frequency should be interpreted as a suggestion that can't always be honored due to how most kernels expose alarms.
302  *
303  * Said that, when using statistical sampling, always assume variable rate sampling as all sort of external factors can interfere.
304  */
305 void
306 mono_profiler_set_statistical_mode (MonoProfileSamplingMode mode, int64_t sampling_frequency_hz)
307 {
308         sampling_mode = mode;
309         sampling_frequency = sampling_frequency_hz;
310 }
311
312 void 
313 mono_profiler_install_statistical (MonoProfileStatFunc callback)
314 {
315         if (!prof_list)
316                 return;
317         prof_list->statistical_cb = callback;
318 }
319
320 int64_t
321 mono_profiler_get_sampling_rate (void)
322 {
323         return sampling_frequency;
324 }
325
326 MonoProfileSamplingMode
327 mono_profiler_get_sampling_mode (void)
328 {
329         return sampling_mode;
330 }
331
332 void 
333 mono_profiler_install_statistical_call_chain (MonoProfileStatCallChainFunc callback, int call_chain_depth, MonoProfilerCallChainStrategy call_chain_strategy) {
334         if (!prof_list)
335                 return;
336         if (call_chain_depth > MONO_PROFILER_MAX_STAT_CALL_CHAIN_DEPTH) {
337                 call_chain_depth = MONO_PROFILER_MAX_STAT_CALL_CHAIN_DEPTH;
338         }
339         if ((call_chain_strategy >= MONO_PROFILER_CALL_CHAIN_INVALID) || (call_chain_strategy < MONO_PROFILER_CALL_CHAIN_NONE)) {
340                 call_chain_strategy = MONO_PROFILER_CALL_CHAIN_NONE;
341         }
342         prof_list->statistical_call_chain_cb = callback;
343         prof_list->statistical_call_chain_depth = call_chain_depth;
344         prof_list->statistical_call_chain_strategy = call_chain_strategy;
345 }
346
347 int
348 mono_profiler_stat_get_call_chain_depth (void) {
349         if (prof_list && prof_list->statistical_call_chain_cb != NULL) {
350                 return prof_list->statistical_call_chain_depth;
351         } else {
352                 return 0;
353         }
354 }
355
356 MonoProfilerCallChainStrategy
357 mono_profiler_stat_get_call_chain_strategy (void) {
358         if (prof_list && prof_list->statistical_call_chain_cb != NULL) {
359                 return prof_list->statistical_call_chain_strategy;
360         } else {
361                 return MONO_PROFILER_CALL_CHAIN_NONE;
362         }
363 }
364
365 void mono_profiler_install_exception (MonoProfileExceptionFunc throw_callback, MonoProfileMethodFunc exc_method_leave, MonoProfileExceptionClauseFunc clause_callback)
366 {
367         if (!prof_list)
368                 return;
369         prof_list->exception_throw_cb = throw_callback;
370         prof_list->exception_method_leave_cb = exc_method_leave;
371         prof_list->exception_clause_cb = clause_callback;
372 }
373
374 void 
375 mono_profiler_install_coverage_filter (MonoProfileCoverageFilterFunc callback)
376 {
377         if (!prof_list)
378                 return;
379         prof_list->coverage_filter_cb = callback;
380 }
381
382 void 
383 mono_profiler_install_appdomain   (MonoProfileAppDomainFunc start_load, MonoProfileAppDomainResult end_load,
384                                    MonoProfileAppDomainFunc start_unload, MonoProfileAppDomainFunc end_unload)
385
386 {
387         if (!prof_list)
388                 return;
389         prof_list->domain_start_load = start_load;
390         prof_list->domain_end_load = end_load;
391         prof_list->domain_start_unload = start_unload;
392         prof_list->domain_end_unload = end_unload;
393 }
394
395 void
396 mono_profiler_install_appdomain_name (MonoProfileAppDomainFriendlyNameFunc domain_name_cb)
397 {
398         if (!prof_list)
399                 return;
400
401         prof_list->domain_name = domain_name_cb;
402 }
403
404 void
405 mono_profiler_install_context (MonoProfileContextFunc load, MonoProfileContextFunc unload)
406 {
407         if (!prof_list)
408                 return;
409
410         prof_list->context_load = load;
411         prof_list->context_unload = unload;
412 }
413
414 void 
415 mono_profiler_install_assembly    (MonoProfileAssemblyFunc start_load, MonoProfileAssemblyResult end_load,
416                                    MonoProfileAssemblyFunc start_unload, MonoProfileAssemblyFunc end_unload)
417 {
418         if (!prof_list)
419                 return;
420         prof_list->assembly_start_load = start_load;
421         prof_list->assembly_end_load = end_load;
422         prof_list->assembly_start_unload = start_unload;
423         prof_list->assembly_end_unload = end_unload;
424 }
425
426 void 
427 mono_profiler_install_module      (MonoProfileModuleFunc start_load, MonoProfileModuleResult end_load,
428                                    MonoProfileModuleFunc start_unload, MonoProfileModuleFunc end_unload)
429 {
430         if (!prof_list)
431                 return;
432         prof_list->module_start_load = start_load;
433         prof_list->module_end_load = end_load;
434         prof_list->module_start_unload = start_unload;
435         prof_list->module_end_unload = end_unload;
436 }
437
438 void
439 mono_profiler_install_class       (MonoProfileClassFunc start_load, MonoProfileClassResult end_load,
440                                    MonoProfileClassFunc start_unload, MonoProfileClassFunc end_unload)
441 {
442         if (!prof_list)
443                 return;
444         prof_list->class_start_load = start_load;
445         prof_list->class_end_load = end_load;
446         prof_list->class_start_unload = start_unload;
447         prof_list->class_end_unload = end_unload;
448 }
449
450 void
451 mono_profiler_method_enter (MonoMethod *method)
452 {
453         ProfilerDesc *prof;
454         for (prof = prof_list; prof; prof = prof->next) {
455                 if ((prof->events & MONO_PROFILE_ENTER_LEAVE) && prof->method_enter)
456                         prof->method_enter (prof->profiler, method);
457         }
458 }
459
460 void
461 mono_profiler_method_leave (MonoMethod *method)
462 {
463         ProfilerDesc *prof;
464         for (prof = prof_list; prof; prof = prof->next) {
465                 if ((prof->events & MONO_PROFILE_ENTER_LEAVE) && prof->method_leave)
466                         prof->method_leave (prof->profiler, method);
467         }
468 }
469
470 void 
471 mono_profiler_method_jit (MonoMethod *method)
472 {
473         ProfilerDesc *prof;
474         for (prof = prof_list; prof; prof = prof->next) {
475                 if ((prof->events & MONO_PROFILE_JIT_COMPILATION) && prof->jit_start)
476                         prof->jit_start (prof->profiler, method);
477         }
478 }
479
480 void 
481 mono_profiler_method_end_jit (MonoMethod *method, MonoJitInfo* jinfo, int result)
482 {
483         ProfilerDesc *prof;
484         for (prof = prof_list; prof; prof = prof->next) {
485                 if ((prof->events & MONO_PROFILE_JIT_COMPILATION)) {
486                         if (prof->jit_end)
487                                 prof->jit_end (prof->profiler, method, result);
488                         if (prof->jit_end2)
489                                 prof->jit_end2 (prof->profiler, method, jinfo, result);
490                 }
491         }
492 }
493
494 void 
495 mono_profiler_method_free (MonoMethod *method)
496 {
497         ProfilerDesc *prof;
498         for (prof = prof_list; prof; prof = prof->next) {
499                 if ((prof->events & MONO_PROFILE_METHOD_EVENTS) && prof->method_free)
500                         prof->method_free (prof->profiler, method);
501         }
502 }
503
504 void
505 mono_profiler_method_start_invoke (MonoMethod *method)
506 {
507         ProfilerDesc *prof;
508         for (prof = prof_list; prof; prof = prof->next) {
509                 if ((prof->events & MONO_PROFILE_METHOD_EVENTS) && prof->method_start_invoke)
510                         prof->method_start_invoke (prof->profiler, method);
511         }
512 }
513
514 void
515 mono_profiler_method_end_invoke (MonoMethod *method)
516 {
517         ProfilerDesc *prof;
518         for (prof = prof_list; prof; prof = prof->next) {
519                 if ((prof->events & MONO_PROFILE_METHOD_EVENTS) && prof->method_end_invoke)
520                         prof->method_end_invoke (prof->profiler, method);
521         }
522 }
523
524 void 
525 mono_profiler_code_transition (MonoMethod *method, int result)
526 {
527         ProfilerDesc *prof;
528         for (prof = prof_list; prof; prof = prof->next) {
529                 if ((prof->events & MONO_PROFILE_TRANSITIONS) && prof->man_unman_transition)
530                         prof->man_unman_transition (prof->profiler, method, result);
531         }
532 }
533
534 void 
535 mono_profiler_allocation (MonoObject *obj)
536 {
537         ProfilerDesc *prof;
538         for (prof = prof_list; prof; prof = prof->next) {
539                 if ((prof->events & MONO_PROFILE_ALLOCATIONS) && prof->allocation_cb)
540                         prof->allocation_cb (prof->profiler, obj, obj->vtable->klass);
541         }
542 }
543
544 void
545 mono_profiler_monitor_event      (MonoObject *obj, MonoProfilerMonitorEvent event) {
546         ProfilerDesc *prof;
547         for (prof = prof_list; prof; prof = prof->next) {
548                 if ((prof->events & MONO_PROFILE_MONITOR_EVENTS) && prof->monitor_event_cb)
549                         prof->monitor_event_cb (prof->profiler, obj, event);
550         }
551 }
552
553 void
554 mono_profiler_stat_hit (guchar *ip, void *context)
555 {
556         ProfilerDesc *prof;
557         for (prof = prof_list; prof; prof = prof->next) {
558                 if ((prof->events & MONO_PROFILE_STATISTICAL) && prof->statistical_cb)
559                         prof->statistical_cb (prof->profiler, ip, context);
560         }
561 }
562
563 void
564 mono_profiler_stat_call_chain (int call_chain_depth, guchar **ips, void *context)
565 {
566         ProfilerDesc *prof;
567         for (prof = prof_list; prof; prof = prof->next) {
568                 if ((prof->events & MONO_PROFILE_STATISTICAL) && prof->statistical_call_chain_cb)
569                         prof->statistical_call_chain_cb (prof->profiler, call_chain_depth, ips, context);
570         }
571 }
572
573 void
574 mono_profiler_exception_thrown (MonoObject *exception)
575 {
576         ProfilerDesc *prof;
577         for (prof = prof_list; prof; prof = prof->next) {
578                 if ((prof->events & MONO_PROFILE_EXCEPTIONS) && prof->exception_throw_cb)
579                         prof->exception_throw_cb (prof->profiler, exception);
580         }
581 }
582
583 void
584 mono_profiler_exception_method_leave (MonoMethod *method)
585 {
586         ProfilerDesc *prof;
587         for (prof = prof_list; prof; prof = prof->next) {
588                 if ((prof->events & MONO_PROFILE_EXCEPTIONS) && prof->exception_method_leave_cb)
589                         prof->exception_method_leave_cb (prof->profiler, method);
590         }
591 }
592
593 void
594 mono_profiler_exception_clause_handler (MonoMethod *method, int clause_type, int clause_num)
595 {
596         ProfilerDesc *prof;
597         for (prof = prof_list; prof; prof = prof->next) {
598                 if ((prof->events & MONO_PROFILE_EXCEPTIONS) && prof->exception_clause_cb)
599                         prof->exception_clause_cb (prof->profiler, method, clause_type, clause_num);
600         }
601 }
602
603 void
604 mono_profiler_thread_start (gsize tid)
605 {
606         ProfilerDesc *prof;
607         for (prof = prof_list; prof; prof = prof->next) {
608                 if ((prof->events & MONO_PROFILE_THREADS) && prof->thread_start)
609                         prof->thread_start (prof->profiler, tid);
610         }
611 }
612
613 void 
614 mono_profiler_thread_end (gsize tid)
615 {
616         ProfilerDesc *prof;
617         for (prof = prof_list; prof; prof = prof->next) {
618                 if ((prof->events & MONO_PROFILE_THREADS) && prof->thread_end)
619                         prof->thread_end (prof->profiler, tid);
620         }
621 }
622
623 void
624 mono_profiler_thread_name (gsize tid, const char *name)
625 {
626         ProfilerDesc *prof;
627         for (prof = prof_list; prof; prof = prof->next) {
628                 if ((prof->events & MONO_PROFILE_THREADS) && prof->thread_name)
629                         prof->thread_name (prof->profiler, tid, name);
630         }
631 }
632
633 void 
634 mono_profiler_assembly_event  (MonoAssembly *assembly, int code)
635 {
636         ProfilerDesc *prof;
637         for (prof = prof_list; prof; prof = prof->next) {
638                 if (!(prof->events & MONO_PROFILE_ASSEMBLY_EVENTS))
639                         continue;
640
641                 switch (code) {
642                 case MONO_PROFILE_START_LOAD:
643                         if (prof->assembly_start_load)
644                                 prof->assembly_start_load (prof->profiler, assembly);
645                         break;
646                 case MONO_PROFILE_START_UNLOAD:
647                         if (prof->assembly_start_unload)
648                                 prof->assembly_start_unload (prof->profiler, assembly);
649                         break;
650                 case MONO_PROFILE_END_UNLOAD:
651                         if (prof->assembly_end_unload)
652                                 prof->assembly_end_unload (prof->profiler, assembly);
653                         break;
654                 default:
655                         g_assert_not_reached ();
656                 }
657         }
658 }
659
660 void 
661 mono_profiler_assembly_loaded (MonoAssembly *assembly, int result)
662 {
663         ProfilerDesc *prof;
664         for (prof = prof_list; prof; prof = prof->next) {
665                 if ((prof->events & MONO_PROFILE_ASSEMBLY_EVENTS) && prof->assembly_end_load)
666                         prof->assembly_end_load (prof->profiler, assembly, result);
667         }
668 }
669
670 void mono_profiler_iomap (char *report, const char *pathname, const char *new_pathname)
671 {
672         ProfilerDesc *prof;
673         for (prof = prof_list; prof; prof = prof->next) {
674                 if ((prof->events & MONO_PROFILE_IOMAP_EVENTS) && prof->iomap_cb)
675                         prof->iomap_cb (prof->profiler, report, pathname, new_pathname);
676         }
677 }
678
679 void 
680 mono_profiler_module_event  (MonoImage *module, int code)
681 {
682         ProfilerDesc *prof;
683         for (prof = prof_list; prof; prof = prof->next) {
684                 if (!(prof->events & MONO_PROFILE_MODULE_EVENTS))
685                         continue;
686
687                 switch (code) {
688                 case MONO_PROFILE_START_LOAD:
689                         if (prof->module_start_load)
690                                 prof->module_start_load (prof->profiler, module);
691                         break;
692                 case MONO_PROFILE_START_UNLOAD:
693                         if (prof->module_start_unload)
694                                 prof->module_start_unload (prof->profiler, module);
695                         break;
696                 case MONO_PROFILE_END_UNLOAD:
697                         if (prof->module_end_unload)
698                                 prof->module_end_unload (prof->profiler, module);
699                         break;
700                 default:
701                         g_assert_not_reached ();
702                 }
703         }
704 }
705
706 void 
707 mono_profiler_module_loaded (MonoImage *module, int result)
708 {
709         ProfilerDesc *prof;
710         for (prof = prof_list; prof; prof = prof->next) {
711                 if ((prof->events & MONO_PROFILE_MODULE_EVENTS) && prof->module_end_load)
712                         prof->module_end_load (prof->profiler, module, result);
713         }
714 }
715
716 void 
717 mono_profiler_class_event  (MonoClass *klass, int code)
718 {
719         ProfilerDesc *prof;
720         for (prof = prof_list; prof; prof = prof->next) {
721                 if (!(prof->events & MONO_PROFILE_CLASS_EVENTS))
722                         continue;
723
724                 switch (code) {
725                 case MONO_PROFILE_START_LOAD:
726                         if (prof->class_start_load)
727                                 prof->class_start_load (prof->profiler, klass);
728                         break;
729                 case MONO_PROFILE_START_UNLOAD:
730                         if (prof->class_start_unload)
731                                 prof->class_start_unload (prof->profiler, klass);
732                         break;
733                 case MONO_PROFILE_END_UNLOAD:
734                         if (prof->class_end_unload)
735                                 prof->class_end_unload (prof->profiler, klass);
736                         break;
737                 default:
738                         g_assert_not_reached ();
739                 }
740         }
741 }
742
743 void 
744 mono_profiler_class_loaded (MonoClass *klass, int result)
745 {
746         ProfilerDesc *prof;
747         for (prof = prof_list; prof; prof = prof->next) {
748                 if ((prof->events & MONO_PROFILE_CLASS_EVENTS) && prof->class_end_load)
749                         prof->class_end_load (prof->profiler, klass, result);
750         }
751 }
752
753 void 
754 mono_profiler_appdomain_event  (MonoDomain *domain, int code)
755 {
756         ProfilerDesc *prof;
757         for (prof = prof_list; prof; prof = prof->next) {
758                 if (!(prof->events & MONO_PROFILE_APPDOMAIN_EVENTS))
759                         continue;
760
761                 switch (code) {
762                 case MONO_PROFILE_START_LOAD:
763                         if (prof->domain_start_load)
764                                 prof->domain_start_load (prof->profiler, domain);
765                         break;
766                 case MONO_PROFILE_START_UNLOAD:
767                         if (prof->domain_start_unload)
768                                 prof->domain_start_unload (prof->profiler, domain);
769                         break;
770                 case MONO_PROFILE_END_UNLOAD:
771                         if (prof->domain_end_unload)
772                                 prof->domain_end_unload (prof->profiler, domain);
773                         break;
774                 default:
775                         g_assert_not_reached ();
776                 }
777         }
778 }
779
780 void 
781 mono_profiler_appdomain_loaded (MonoDomain *domain, int result)
782 {
783         ProfilerDesc *prof;
784         for (prof = prof_list; prof; prof = prof->next) {
785                 if ((prof->events & MONO_PROFILE_APPDOMAIN_EVENTS) && prof->domain_end_load)
786                         prof->domain_end_load (prof->profiler, domain, result);
787         }
788 }
789
790 void
791 mono_profiler_appdomain_name (MonoDomain *domain, const char *name)
792 {
793         for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
794                 if ((prof->events & MONO_PROFILE_APPDOMAIN_EVENTS) && prof->domain_name)
795                         prof->domain_name (prof->profiler, domain, name);
796 }
797
798 void
799 mono_profiler_context_loaded (MonoAppContext *context)
800 {
801         for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
802                 if ((prof->events & MONO_PROFILE_CONTEXT_EVENTS) && prof->context_load)
803                         prof->context_load (prof->profiler, context);
804 }
805
806 void
807 mono_profiler_context_unloaded (MonoAppContext *context)
808 {
809         for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
810                 if ((prof->events & MONO_PROFILE_CONTEXT_EVENTS) && prof->context_unload)
811                         prof->context_unload (prof->profiler, context);
812 }
813
814 void 
815 mono_profiler_shutdown (void)
816 {
817         ProfilerDesc *prof;
818         for (prof = prof_list; prof; prof = prof->next) {
819                 if (prof->shutdown_callback)
820                         prof->shutdown_callback (prof->profiler);
821         }
822
823         mono_profiler_set_events ((MonoProfileFlags)0);
824 }
825
826 void
827 mono_profiler_gc_heap_resize (gint64 new_size)
828 {
829         ProfilerDesc *prof;
830         for (prof = prof_list; prof; prof = prof->next) {
831                 if ((prof->events & MONO_PROFILE_GC) && prof->gc_heap_resize)
832                         prof->gc_heap_resize (prof->profiler, new_size);
833         }
834 }
835
836 void
837 mono_profiler_gc_event (MonoGCEvent event, int generation)
838 {
839         ProfilerDesc *prof;
840         for (prof = prof_list; prof; prof = prof->next) {
841                 if ((prof->events & MONO_PROFILE_GC) && prof->gc_event)
842                         prof->gc_event (prof->profiler, event, generation);
843         }
844 }
845
846 void
847 mono_profiler_gc_moves (void **objects, int num)
848 {
849         ProfilerDesc *prof;
850         for (prof = prof_list; prof; prof = prof->next) {
851                 if ((prof->events & MONO_PROFILE_GC_MOVES) && prof->gc_moves)
852                         prof->gc_moves (prof->profiler, objects, num);
853         }
854 }
855
856 void
857 mono_profiler_gc_handle (int op, int type, uintptr_t handle, MonoObject *obj)
858 {
859         ProfilerDesc *prof;
860         for (prof = prof_list; prof; prof = prof->next) {
861                 if ((prof->events & MONO_PROFILE_GC_ROOTS) && prof->gc_handle)
862                         prof->gc_handle (prof->profiler, op, type, handle, obj);
863         }
864 }
865
866 void
867 mono_profiler_gc_roots (int num, void **objects, int *root_types, uintptr_t *extra_info)
868 {
869         ProfilerDesc *prof;
870         for (prof = prof_list; prof; prof = prof->next) {
871                 if ((prof->events & MONO_PROFILE_GC_ROOTS) && prof->gc_roots)
872                         prof->gc_roots (prof->profiler, num, objects, root_types, extra_info);
873         }
874 }
875
876 void
877 mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback)
878 {
879         mono_gc_enable_events ();
880         if (!prof_list)
881                 return;
882         prof_list->gc_event = callback;
883         prof_list->gc_heap_resize = heap_resize_callback;
884 }
885
886 /**
887  * mono_profiler_install_gc_moves:
888  * @callback: callback function
889  *
890  * Install the @callback function that the GC will call when moving objects.
891  * The callback receives an array of pointers and the number of elements
892  * in the array. Every even element in the array is the original object location
893  * and the following odd element is the new location of the object in memory.
894  * So the number of elements argument will always be a multiple of 2.
895  * Since this callback happens during the GC, it is a restricted environment:
896  * no locks can be taken and the object pointers can be inspected only once
897  * the GC is finished (of course the original location pointers will not
898  * point to valid objects anymore).
899  */
900 void
901 mono_profiler_install_gc_moves (MonoProfileGCMoveFunc callback)
902 {
903         if (!prof_list)
904                 return;
905         prof_list->gc_moves = callback;
906 }
907
908 /**
909  * mono_profiler_install_gc_roots:
910  * @handle_callback: callback function
911  * @roots_callback: callback function
912  *
913  * Install the @handle_callback function that the GC will call when GC
914  * handles are created or destroyed.
915  * The callback receives an operation, which is either #MONO_PROFILER_GC_HANDLE_CREATED
916  * or #MONO_PROFILER_GC_HANDLE_DESTROYED, the handle type, the handle value and the
917  * object pointer, if present.
918  * Install the @roots_callback function that the GC will call when tracing
919  * the roots for a collection.
920  * The callback receives the number of elements and three arrays: an array
921  * of objects, an array of root types and flags and an array of extra info.
922  * The size of each array is given by the first argument.
923  */
924 void
925 mono_profiler_install_gc_roots (MonoProfileGCHandleFunc handle_callback, MonoProfileGCRootFunc roots_callback)
926 {
927         if (!prof_list)
928                 return;
929         prof_list->gc_handle = handle_callback;
930         prof_list->gc_roots = roots_callback;
931 }
932
933 void
934 mono_profiler_gc_finalize_begin (void)
935 {
936         for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
937                 if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_begin)
938                         prof->gc_finalize_begin (prof->profiler);
939 }
940
941 void
942 mono_profiler_gc_finalize_object_begin (MonoObject *obj)
943 {
944         for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
945                 if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_object_begin)
946                         prof->gc_finalize_object_begin (prof->profiler, obj);
947 }
948
949 void
950 mono_profiler_gc_finalize_object_end (MonoObject *obj)
951 {
952         for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
953                 if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_object_end)
954                         prof->gc_finalize_object_end (prof->profiler, obj);
955 }
956
957 void
958 mono_profiler_gc_finalize_end (void)
959 {
960         for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
961                 if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_end)
962                         prof->gc_finalize_end (prof->profiler);
963 }
964
965 void
966 mono_profiler_install_gc_finalize (MonoProfileGCFinalizeFunc begin, MonoProfileGCFinalizeObjectFunc begin_obj, MonoProfileGCFinalizeObjectFunc end_obj, MonoProfileGCFinalizeFunc end)
967 {
968         if (!prof_list)
969                 return;
970
971         prof_list->gc_finalize_begin = begin;
972         prof_list->gc_finalize_object_begin = begin_obj;
973         prof_list->gc_finalize_object_begin = end_obj;
974         prof_list->gc_finalize_end = end;
975 }
976
977 void
978 mono_profiler_install_runtime_initialized (MonoProfileFunc runtime_initialized_callback)
979 {
980         if (!prof_list)
981                 return;
982         prof_list->runtime_initialized_event = runtime_initialized_callback;
983 }
984
985 void
986 mono_profiler_runtime_initialized (void) {
987         ProfilerDesc *prof;
988         for (prof = prof_list; prof; prof = prof->next) {
989                 if (prof->runtime_initialized_event)
990                         prof->runtime_initialized_event (prof->profiler);
991         }
992 }
993
994 void
995 mono_profiler_install_code_chunk_new (MonoProfilerCodeChunkNew callback) {
996         if (!prof_list)
997                 return;
998         prof_list->code_chunk_new = callback;
999 }
1000 void
1001 mono_profiler_code_chunk_new (gpointer chunk, int size) {
1002         ProfilerDesc *prof;
1003         for (prof = prof_list; prof; prof = prof->next) {
1004                 if (prof->code_chunk_new)
1005                         prof->code_chunk_new (prof->profiler, chunk, size);
1006         }
1007 }
1008
1009 void
1010 mono_profiler_install_code_chunk_destroy (MonoProfilerCodeChunkDestroy callback) {
1011         if (!prof_list)
1012                 return;
1013         prof_list->code_chunk_destroy = callback;
1014 }
1015 void
1016 mono_profiler_code_chunk_destroy (gpointer chunk) {
1017         ProfilerDesc *prof;
1018         for (prof = prof_list; prof; prof = prof->next) {
1019                 if (prof->code_chunk_destroy)
1020                         prof->code_chunk_destroy (prof->profiler, chunk);
1021         }
1022 }
1023
1024 void
1025 mono_profiler_install_code_buffer_new (MonoProfilerCodeBufferNew callback) {
1026         if (!prof_list)
1027                 return;
1028         prof_list->code_buffer_new = callback;
1029 }
1030
1031 void
1032 mono_profiler_install_iomap (MonoProfileIomapFunc callback)
1033 {
1034         if (!prof_list)
1035                 return;
1036         prof_list->iomap_cb = callback;
1037 }
1038
1039 void
1040 mono_profiler_code_buffer_new (gpointer buffer, int size, MonoProfilerCodeBufferType type, gconstpointer data) {
1041         ProfilerDesc *prof;
1042         for (prof = prof_list; prof; prof = prof->next) {
1043                 if (prof->code_buffer_new)
1044                         prof->code_buffer_new (prof->profiler, buffer, size, type, (void*)data);
1045         }
1046 }
1047
1048 static GHashTable *coverage_hash = NULL;
1049
1050 MonoProfileCoverageInfo* 
1051 mono_profiler_coverage_alloc (MonoMethod *method, int entries)
1052 {
1053         MonoProfileCoverageInfo *res;
1054         int instrument = FALSE;
1055         ProfilerDesc *prof;
1056
1057         for (prof = prof_list; prof; prof = prof->next) {
1058                 /* note that we call the filter on all the profilers even if just
1059                  * a single one would be enough to instrument a method
1060                  */
1061                 if (prof->coverage_filter_cb)
1062                         if (prof->coverage_filter_cb (prof->profiler, method))
1063                                 instrument = TRUE;
1064         }
1065         if (!instrument)
1066                 return NULL;
1067
1068         mono_profiler_coverage_lock ();
1069         if (!coverage_hash)
1070                 coverage_hash = g_hash_table_new (NULL, NULL);
1071
1072         res = (MonoProfileCoverageInfo *)g_malloc0 (sizeof (MonoProfileCoverageInfo) + sizeof (void*) * 2 * entries);
1073
1074         res->entries = entries;
1075
1076         g_hash_table_insert (coverage_hash, method, res);
1077         mono_profiler_coverage_unlock ();
1078
1079         return res;
1080 }
1081
1082 /* safe only when the method antive code has been unloaded */
1083 void
1084 mono_profiler_coverage_free (MonoMethod *method)
1085 {
1086         MonoProfileCoverageInfo* info;
1087
1088         mono_profiler_coverage_lock ();
1089         if (!coverage_hash) {
1090                 mono_profiler_coverage_unlock ();
1091                 return;
1092         }
1093
1094         info = (MonoProfileCoverageInfo *)g_hash_table_lookup (coverage_hash, method);
1095         if (info) {
1096                 g_free (info);
1097                 g_hash_table_remove (coverage_hash, method);
1098         }
1099         mono_profiler_coverage_unlock ();
1100 }
1101
1102 /**
1103  * mono_profiler_coverage_get:
1104  * @prof: The profiler handle, installed with mono_profiler_install
1105  * @method: the method to gather information from.
1106  * @func: A routine that will be called back with the results
1107  *
1108  * If the MONO_PROFILER_INS_COVERAGE flag was active during JIT compilation
1109  * it is posisble to obtain coverage information about a give method.
1110  *
1111  * The function @func will be invoked repeatedly with instances of the
1112  * MonoProfileCoverageEntry structure.
1113  */
1114 void 
1115 mono_profiler_coverage_get (MonoProfiler *prof, MonoMethod *method, MonoProfileCoverageFunc func)
1116 {
1117         MonoError error;
1118         MonoProfileCoverageInfo* info = NULL;
1119         int i, offset;
1120         guint32 code_size;
1121         const unsigned char *start, *end, *cil_code;
1122         MonoMethodHeader *header;
1123         MonoProfileCoverageEntry entry;
1124         MonoDebugMethodInfo *debug_minfo;
1125
1126         mono_profiler_coverage_lock ();
1127         if (coverage_hash)
1128                 info = (MonoProfileCoverageInfo *)g_hash_table_lookup (coverage_hash, method);
1129         mono_profiler_coverage_unlock ();
1130
1131         if (!info)
1132                 return;
1133
1134         header = mono_method_get_header_checked (method, &error);
1135         mono_error_assert_ok (&error);
1136         start = mono_method_header_get_code (header, &code_size, NULL);
1137         debug_minfo = mono_debug_lookup_method (method);
1138
1139         end = start + code_size;
1140         for (i = 0; i < info->entries; ++i) {
1141                 cil_code = info->data [i].cil_code;
1142                 if (cil_code && cil_code >= start && cil_code < end) {
1143                         char *fname = NULL;
1144                         offset = cil_code - start;
1145                         entry.iloffset = offset;
1146                         entry.method = method;
1147                         entry.counter = info->data [i].count;
1148                         entry.line = entry.col = 1;
1149                         entry.filename = NULL;
1150                         if (debug_minfo) {
1151                                 MonoDebugSourceLocation *location;
1152
1153                                 location = mono_debug_symfile_lookup_location (debug_minfo, offset);
1154                                 if (location) {
1155                                         entry.line = location->row;
1156                                         entry.col = location->column;
1157                                         entry.filename = fname = g_strdup (location->source_file);
1158                                         mono_debug_free_source_location (location);
1159                                 }
1160                         }
1161
1162                         func (prof, &entry);
1163                         g_free (fname);
1164                 }
1165         }
1166         mono_metadata_free_mh (header);
1167 }
1168
1169 typedef void (*ProfilerInitializer) (const char*);
1170 #define INITIALIZER_NAME "mono_profiler_startup"
1171
1172
1173 static gboolean
1174 load_profiler (MonoDl *pmodule, const char *desc, const char *symbol)
1175 {
1176         char *err;
1177         ProfilerInitializer func;
1178
1179         if (!pmodule)
1180                 return FALSE;
1181
1182         if ((err = mono_dl_symbol (pmodule, symbol, (gpointer *) &func))) {
1183                 g_free (err);
1184                 return FALSE;
1185         } else {
1186                 func (desc);
1187         }
1188         return TRUE;
1189 }
1190
1191 static gboolean
1192 load_embedded_profiler (const char *desc, const char *name)
1193 {
1194         char *err = NULL;
1195         char *symbol;
1196         MonoDl *pmodule = NULL;
1197         gboolean result;
1198
1199         /*
1200          * Some profilers (such as ours) may need to call back into the runtime
1201          * from their sampling callback (which is called in async-signal context).
1202          * They need to be able to know that all references back to the runtime
1203          * have been resolved; otherwise, calling runtime functions may result in
1204          * invoking the dynamic linker which is not async-signal-safe. Passing
1205          * MONO_DL_EAGER will ask the dynamic linker to resolve everything upfront.
1206          */
1207         pmodule = mono_dl_open (NULL, MONO_DL_EAGER, &err);
1208         if (!pmodule) {
1209                 g_warning ("Could not open main executable (%s)", err);
1210                 g_free (err);
1211                 return FALSE;
1212         }
1213
1214         symbol = g_strdup_printf (INITIALIZER_NAME "_%s", name);
1215         result = load_profiler (pmodule, desc, symbol);
1216         g_free (symbol);
1217
1218         return result;
1219 }
1220
1221 // TODO: Much of the library loading code here is custom. It would be better to merge this with mono-dl
1222 static gboolean
1223 load_profiler_from_directory (const char *directory, const char *libname, const char *desc)
1224 {
1225         MonoDl *pmodule = NULL;
1226         char* path;
1227         char *err;
1228         void *iter;
1229
1230         mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler %s from %s (desc %s)", libname, directory, desc);
1231
1232         iter = NULL;
1233         err = NULL;
1234         while ((path = mono_dl_build_path (directory, libname, &iter))) {
1235                 pmodule = mono_dl_open (path, MONO_DL_EAGER, &err);
1236                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler: %s, %ssuccessful, err: %s", path, pmodule?"":"not ", err);
1237                 g_free (path);
1238                 g_free (err);
1239                 if (pmodule)
1240                         return load_profiler (pmodule, desc, INITIALIZER_NAME);
1241         }
1242                 
1243         return FALSE;
1244 }
1245
1246 static gboolean
1247 load_profiler_from_mono_installation (const char *libname, const char *desc)
1248 {
1249         char *err = NULL;
1250         MonoDl *pmodule = mono_dl_open_runtime_lib (libname, MONO_DL_EAGER, &err);
1251         mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler from runtime libs: %s, %ssuccessful, err: %s", libname, pmodule?"":"not ", err);
1252         g_free (err);
1253         if (pmodule)
1254                 return load_profiler (pmodule, desc, INITIALIZER_NAME);
1255         return FALSE;
1256 }
1257
1258 /**
1259  * mono_profiler_load:
1260  * @desc: arguments to configure the profiler
1261  *
1262  * Invoke this method to initialize the profiler.   This will drive the
1263  * loading of the internal ("default") or any external profilers.
1264  *
1265  * This routine is invoked by Mono's driver, but must be called manually
1266  * if you embed Mono into your application.
1267  */
1268 void 
1269 mono_profiler_load (const char *desc)
1270 {
1271         char *cdesc = NULL;
1272         mono_gc_base_init ();
1273
1274         if (!desc || (strcmp ("default", desc) == 0)) {
1275                 desc = "log:report";
1276         }
1277         /* we keep command-line compat with the old version here */
1278         if (strncmp (desc, "default:", 8) == 0) {
1279                 gchar **args, **ptr;
1280                 GString *str = g_string_new ("log:report");
1281                 args = g_strsplit (desc + 8, ",", -1);
1282                 for (ptr = args; ptr && *ptr; ptr++) {
1283                         const char *arg = *ptr;
1284
1285                         if (!strcmp (arg, "time"))
1286                                 g_string_append (str, ",calls");
1287                         else if (!strcmp (arg, "alloc"))
1288                                 g_string_append (str, ",alloc");
1289                         else if (!strcmp (arg, "stat"))
1290                                 g_string_append (str, ",sample");
1291                         else if (!strcmp (arg, "jit"))
1292                                 continue; /* accept and do nothing */
1293                         else if (strncmp (arg, "file=", 5) == 0) {
1294                                 g_string_append_printf (str, ",output=%s", arg + 5);
1295                         } else {
1296                                 fprintf (stderr, "profiler : Unknown argument '%s'.\n", arg);
1297                                 return;
1298                         }
1299                 }
1300                 desc = cdesc = g_string_free (str, FALSE);
1301         }
1302         {
1303                 const char* col = strchr (desc, ':');
1304                 char* libname;
1305                 char *mname;
1306                 gboolean res = FALSE;
1307
1308                 if (col != NULL) {
1309                         mname = (char *)g_memdup (desc, col - desc + 1);
1310                         mname [col - desc] = 0;
1311                 } else {
1312                         mname = g_strdup (desc);
1313                 }
1314                 if (!load_embedded_profiler (desc, mname)) {
1315                         libname = g_strdup_printf ("mono-profiler-%s", mname);
1316                         res = load_profiler_from_mono_installation (libname, desc);
1317                         if (!res && mono_config_get_assemblies_dir ())
1318                                 res = load_profiler_from_directory (mono_assembly_getrootdir (), libname, desc);
1319                         if (!res)
1320                                 res = load_profiler_from_directory (NULL, libname, desc);
1321                         if (!res)
1322                                 g_warning ("The '%s' profiler wasn't found in the main executable nor could it be loaded from '%s'.", mname, libname);
1323                         g_free (libname);
1324                 }
1325                 g_free (mname);
1326         }
1327         g_free (cdesc);
1328 }
1329